标签流控件

来源:互联网 发布:手机淘宝流量劫持 编辑:程序博客网 时间:2024/06/09 23:27

标签流LabelsView

自定义控件代码

public class LabelsView extends ViewGroup implements View.OnClickListener {    private Context mContext;    private ColorStateList mTextColor;    private float mTextSize;    private int mLabelBgResId;    private int mTextPaddingLeft;    private int mTextPaddingTop;    private int mTextPaddingRight;    private int mTextPaddingBottom;    private int mWordMargin;    private int mLineMargin;    private SelectType mSelectType;    private int mMaxSelect;    private ArrayList<String> mLabels = new ArrayList<>();    //保存选中的label的位置    private ArrayList<Integer> mSelectLabels = new ArrayList<>();    private OnLabelClickListener mLabelClickListener;    private OnLabelSelectChangeListener mLabelSelectChangeListener;    /**     * Label的选择类型     */    public enum SelectType {        //不可选中,也不响应选中事件回调。(默认)        NONE(1),        //单选        SINGLE(2),        //多选        MULTI(3);        int value;        SelectType(int value) {            this.value = value;        }        static SelectType get(int value) {            switch (value) {                case 1:                    return NONE;                case 2:                    return SINGLE;                case 3:                    return MULTI;            }            return NONE;        }    }    public LabelsView(Context context) {        super(context);        mContext = context;    }    public LabelsView(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;        getAttrs(context, attrs);    }    public LabelsView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        getAttrs(context, attrs);    }    private void getAttrs(Context context, AttributeSet attrs) {        if (attrs != null) {            TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.labels_view);            int type = mTypedArray.getInt(R.styleable.labels_view_selectType, 1);            mSelectType = SelectType.get(type);            mMaxSelect = mTypedArray.getInteger(R.styleable.labels_view_maxSelect, 0);            mTextColor = mTypedArray.getColorStateList(R.styleable.labels_view_labelTextColor);            mTextSize = mTypedArray.getDimension(R.styleable.labels_view_labelTextSize,                    sp2px(context, 14));            mTextPaddingLeft = mTypedArray.getDimensionPixelOffset(                    R.styleable.labels_view_labelTextPaddingLeft, 0);            mTextPaddingTop = mTypedArray.getDimensionPixelOffset(                    R.styleable.labels_view_labelTextPaddingTop, 0);            mTextPaddingRight = mTypedArray.getDimensionPixelOffset(                    R.styleable.labels_view_labelTextPaddingRight, 0);            mTextPaddingBottom = mTypedArray.getDimensionPixelOffset(                    R.styleable.labels_view_labelTextPaddingBottom, 0);            mLineMargin = mTypedArray.getDimensionPixelOffset(R.styleable.labels_view_lineMargin, 0);            mWordMargin = mTypedArray.getDimensionPixelOffset(R.styleable.labels_view_wordMargin, 0);            mLabelBgResId = mTypedArray.getResourceId(R.styleable.labels_view_labelBackground, 0);            mTypedArray.recycle();        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int count = getChildCount();        int maxWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();        int contentHeight = 0; //记录内容的高度        int lineWidth = 0; //记录行的宽度        int maxLineWidth = 0; //记录最宽的行宽        int maxItemHeight = 0; //记录一行中item高度最大的高度        boolean begin = true; //是否是行的开头        for (int i = 0; i < count; i++) {            View view = getChildAt(i);            measureChild(view, widthMeasureSpec, heightMeasureSpec);            if (maxWidth < lineWidth + view.getMeasuredWidth()) {                contentHeight += mLineMargin;                contentHeight += maxItemHeight;                maxItemHeight = 0;                maxLineWidth = Math.max(maxLineWidth, lineWidth);                lineWidth = 0;                begin = true;            }            maxItemHeight = Math.max(maxItemHeight, view.getMeasuredHeight());            if (!begin) {                lineWidth += mWordMargin;            } else {                begin = false;            }            lineWidth += view.getMeasuredWidth();        }        contentHeight += maxItemHeight;        maxLineWidth = Math.max(maxLineWidth, lineWidth);        setMeasuredDimension(measureWidth(widthMeasureSpec, maxLineWidth),                measureHeight(heightMeasureSpec, contentHeight));    }    private int measureWidth(int measureSpec, int contentWidth) {        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            result = specSize;        } else {            result = contentWidth + getPaddingLeft() + getPaddingRight();            if (specMode == MeasureSpec.AT_MOST) {                result = Math.min(result, specSize);            }        }        result = Math.max(result, getSuggestedMinimumWidth());        return result;    }    private int measureHeight(int measureSpec, int contentHeight) {        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            result = specSize;        } else {            result = contentHeight + getPaddingTop() + getPaddingBottom();            if (specMode == MeasureSpec.AT_MOST) {                result = Math.min(result, specSize);            }        }        result = Math.max(result, getSuggestedMinimumHeight());        return result;    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        int x = getPaddingLeft();        int y = getPaddingTop();        int contentWidth = right - left;        int maxItemHeight = 0;        int count = getChildCount();        for (int i = 0; i < count; i++) {            View view = getChildAt(i);            if (contentWidth < x + view.getMeasuredWidth() + getPaddingRight()) {                    x = getPaddingLeft();                    y += mLineMargin;                    y += maxItemHeight;                    maxItemHeight = 0;            }//            if ((i+1)%3==0){//                x = getPaddingLeft();//                y += mLineMargin;//                y += maxItemHeight;//                maxItemHeight = 0;//            }            view.layout(x, y, x + view.getMeasuredWidth(), y + view.getMeasuredHeight());            x += view.getMeasuredWidth();            x += mWordMargin;            maxItemHeight = Math.max(maxItemHeight, view.getMeasuredHeight());        }    }    /*  用于保存View的信息的key  */    private static final String KEY_SUPER_STATE = "key_super_state";    private static final String KEY_TEXT_COLOR_STATE = "key_text_color_state";    private static final String KEY_TEXT_SIZE_STATE = "key_text_size_state";    private static final String KEY_BG_RES_ID_STATE = "key_bg_res_id_state";    private static final String KEY_PADDING_STATE = "key_padding_state";    private static final String KEY_WORD_MARGIN_STATE = "key_word_margin_state";    private static final String KEY_LINE_MARGIN_STATE = "key_line_margin_state";    private static final String KEY_SELECT_TYPE_STATE = "key_select_type_state";    private static final String KEY_MAX_SELECT_STATE = "key_max_select_state";    private static final String KEY_LABELS_STATE = "key_labels_state";    private static final String KEY_SELECT_LABELS_STATE = "key_select_labels_state";    @Override    public Parcelable onSaveInstanceState() {        Bundle bundle = new Bundle();        //保存父类的信息        bundle.putParcelable(KEY_SUPER_STATE, super.onSaveInstanceState());        //保存标签文字颜色        if (mTextColor != null) {            bundle.putParcelable(KEY_TEXT_COLOR_STATE, mTextColor);        }        //保存标签文字大小        bundle.putFloat(KEY_TEXT_SIZE_STATE, mTextSize);        //保存标签背景        bundle.putInt(KEY_BG_RES_ID_STATE, mLabelBgResId);        //保存标签内边距        bundle.putIntArray(KEY_PADDING_STATE, new int[]{mTextPaddingLeft, mTextPaddingTop,                mTextPaddingRight, mTextPaddingBottom});        //保存标签间隔        bundle.putInt(KEY_WORD_MARGIN_STATE, mWordMargin);        //保存行间隔        bundle.putInt(KEY_LINE_MARGIN_STATE, mLineMargin);        //保存标签的选择类型        bundle.putInt(KEY_SELECT_TYPE_STATE, mSelectType.value);        //保存标签的最大选择数量        bundle.putInt(KEY_MAX_SELECT_STATE, mMaxSelect);        //保存标签列表        if (!mLabels.isEmpty()) {            bundle.putStringArrayList(KEY_LABELS_STATE, mLabels);        }        //保存已选择的标签列表        if (!mSelectLabels.isEmpty()) {            bundle.putIntegerArrayList(KEY_SELECT_LABELS_STATE, mSelectLabels);        }        return bundle;    }    @Override    public void onRestoreInstanceState(Parcelable state) {        if (state instanceof Bundle) {            Bundle bundle = (Bundle) state;            //恢复父类信息            super.onRestoreInstanceState(bundle.getParcelable(KEY_SUPER_STATE));            //恢复标签文字颜色            ColorStateList color = bundle.getParcelable(KEY_TEXT_COLOR_STATE);            if (color != null) {                setLabelTextColor(color);            }            //恢复标签文字大小            setLabelTextSize(bundle.getFloat(KEY_TEXT_SIZE_STATE, mTextSize));            //恢复标签背景            int resId = bundle.getInt(KEY_BG_RES_ID_STATE, mLabelBgResId);            if (resId != 0) {                setLabelBackgroundResource(resId);            }            //恢复标签内边距            int[] padding = bundle.getIntArray(KEY_PADDING_STATE);            if (padding != null && padding.length == 4) {                setLabelTextPadding(padding[0], padding[1], padding[2], padding[3]);            }            //恢复标签间隔            setWordMargin(bundle.getInt(KEY_WORD_MARGIN_STATE, mWordMargin));            //恢复行间隔            setLineMargin(bundle.getInt(KEY_LINE_MARGIN_STATE, mLineMargin));            //恢复标签的选择类型            setSelectType(SelectType.get(bundle.getInt(KEY_SELECT_TYPE_STATE, mSelectType.value)));            //恢复标签的最大选择数量            setMaxSelect(bundle.getInt(KEY_MAX_SELECT_STATE, mMaxSelect));            //恢复标签列表            ArrayList<String> labels = bundle.getStringArrayList(KEY_LABELS_STATE);            if (labels != null && !labels.isEmpty()) {                setLabels(labels);            }            //恢复已选择的标签列表            ArrayList<Integer> selectLabel = bundle.getIntegerArrayList(KEY_SELECT_LABELS_STATE);            if (selectLabel != null && !selectLabel.isEmpty()) {                int size = selectLabel.size();//                int[] positions = new int[size];//                for (int i = 0; i < size; i++) {//                    positions[i] = selectLabel.get(i);//                }                ArrayList<Integer> positions=new ArrayList<>();                for (int i = 0; i < size; i++) {                    positions.add(selectLabel.get(i)) ;                }                setSelects(positions);            }            return;        }        super.onRestoreInstanceState(state);    }    /**     * 设置标签列表     *     * @param labels     */    public void setLabels(ArrayList<String> labels) {        //清空原有的标签        clearAllSelect();        removeAllViews();        mLabels.clear();        if (labels != null) {            mLabels.addAll(labels);            int size = labels.size();            for (int i = 0; i < size; i++) {                addLabel(labels.get(i), i);            }        }    }    /**     * 获取标签列表     *     * @return     */    public ArrayList<String> getLabels() {        return mLabels;    }    public void Add(String label){        mLabels.add(label);    }    private void addLabel(String text, int position) {        final TextView label = new TextView(mContext);        label.setPadding(mTextPaddingLeft, mTextPaddingTop, mTextPaddingRight, mTextPaddingBottom);        label.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);        label.setTextColor(mTextColor != null ? mTextColor : ColorStateList.valueOf(0xFF000000));        label.setText(text);        if (mLabelBgResId != 0) {            label.setBackgroundResource(mLabelBgResId);        }        //label通过tag保存自己的位置(position)        label.setTag(position);        label.setOnClickListener(this);        addView(label);    }    @Override    public void onClick(View v) {        if (v instanceof TextView) {            TextView label = (TextView) v;            if (mSelectType != SelectType.NONE) {                if (label.isSelected()) {                    setLabelSelect(label, false);                } else if (mSelectType == SelectType.SINGLE) {                    clearAllSelect();                    setLabelSelect(label, true);                } else if (mSelectType == SelectType.MULTI                        && (mMaxSelect <= 0 || mMaxSelect > mSelectLabels.size())) {                    setLabelSelect(label, true);                }            }            if (mLabelClickListener != null) {                mLabelClickListener.onLabelClick(label, label.getText().toString(), (int) v.getTag());            }        }    }    private void setLabelSelect(TextView label, boolean isSelect) {        if (label.isSelected() != isSelect) {            label.setSelected(isSelect);            if (isSelect) {                mSelectLabels.add((Integer) label.getTag());            } else {                mSelectLabels.remove((Integer) label.getTag());            }            if (mLabelSelectChangeListener != null) {                mLabelSelectChangeListener.onLabelSelectChange(label, label.getText().toString(),                        isSelect, (int) label.getTag());            }        }    }    /**     * 取消所有选中的label     */    public void clearAllSelect() {        int count = getChildCount();        for (int i = 0; i < count; i++) {            setLabelSelect((TextView) getChildAt(i), false);        }        mSelectLabels.clear();    }    /**     * 设置选中label     *     * @param positions     */    public void setSelects(ArrayList<Integer> positions) {        if (mSelectType != SelectType.NONE) {            ArrayList<TextView> selectLabels = new ArrayList<>();            int count = getChildCount();            int size = mSelectType == SelectType.SINGLE ? 1 : mMaxSelect;            for (int p : positions) {                if (p < count) {                    TextView label = (TextView) getChildAt(p);                    if (!selectLabels.contains(label)) {                                             setLabelSelect(label, true);                        selectLabels.add(label);                    }                    if (size > 0 && selectLabels.size() == size) {                        break;                    }                }            }            for (int i = 0; i < count; i++) {                TextView label = (TextView) getChildAt(i);                if (!selectLabels.contains(label)) {                    setLabelSelect(label, false);                }            }        }    }    /**     * 获取选中的label     *     * @return     */    public ArrayList<Integer> getSelectLabels() {        return mSelectLabels;    }    /**     * 设置标签背景     *     * @param resId     */    public void setLabelBackgroundResource(int resId) {        if (mLabelBgResId != resId) {            mLabelBgResId = resId;            int count = getChildCount();            for (int i = 0; i < count; i++) {                TextView label = (TextView) getChildAt(i);                label.setBackgroundResource(mLabelBgResId);            }        }    }    /**     * 设置标签内边距     *     * @param left     * @param top     * @param right     * @param bottom     */    public void setLabelTextPadding(int left, int top, int right, int bottom) {        if (mTextPaddingLeft != left || mTextPaddingTop != top                || mTextPaddingRight != right || mTextPaddingBottom != bottom) {            mTextPaddingLeft = left;            mTextPaddingTop = top;            mTextPaddingRight = right;            mTextPaddingBottom = bottom;            int count = getChildCount();            for (int i = 0; i < count; i++) {                TextView label = (TextView) getChildAt(i);                label.setPadding(left, top, right, bottom);            }        }    }    public int getTextPaddingLeft() {        return mTextPaddingLeft;    }    public int getTextPaddingTop() {        return mTextPaddingTop;    }    public int getTextPaddingRight() {        return mTextPaddingRight;    }    public int getTextPaddingBottom() {        return mTextPaddingBottom;    }    /**     * 设置标签的文字大小(单位是px)     *     * @param size     */    public void setLabelTextSize(float size) {        if (mTextSize != size) {            mTextSize = size;            int count = getChildCount();            for (int i = 0; i < count; i++) {                TextView label = (TextView) getChildAt(i);                label.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);            }        }    }    public float getLabelTextSize() {        return mTextSize;    }    /**     * 设置标签的文字颜色     *     * @param color     */    public void setLabelTextColor(int color) {        setLabelTextColor(ColorStateList.valueOf(color));    }    /**     * 设置标签的文字颜色     *     * @param color     */    public void setLabelTextColor(ColorStateList color) {        mTextColor = color;        int count = getChildCount();        for (int i = 0; i < count; i++) {            TextView label = (TextView) getChildAt(i);            label.setTextColor(mTextColor != null ? mTextColor : ColorStateList.valueOf(0xFF000000));        }    }    public ColorStateList getLabelTextColor() {        return mTextColor;    }    /**     * 设置行间隔     */    public void setLineMargin(int margin) {        if (mLineMargin != margin) {            mLineMargin = margin;            requestLayout();        }    }    public int getLineMargin() {        return mLineMargin;    }    /**     * 设置标签的间隔     */    public void setWordMargin(int margin) {        if (mWordMargin != margin) {            mWordMargin = margin;            requestLayout();        }    }    public int getWordMargin() {        return mWordMargin;    }    /**     * 设置标签的选择类型     *     * @param selectType     */    public void setSelectType(SelectType selectType) {        if (mSelectType != selectType) {            mSelectType = selectType;            //选择类型发生改变,就要恢复到初始状态。            clearAllSelect();        }    }    public SelectType getSelectType() {        return mSelectType;    }    /**     * 设置最大的选择数量     *     * @param maxSelect     */    public void setMaxSelect(int maxSelect) {        if (mMaxSelect != maxSelect) {            mMaxSelect = maxSelect;            if (mSelectType == SelectType.MULTI) {                //最大选择数量发生改变,就要恢复到初始状态。                clearAllSelect();            }        }    }    public int getMaxSelect() {        return mMaxSelect;    }    /**     * 设置标签的点击监听     *     * @param l     */    public void setOnLabelClickListener(OnLabelClickListener l) {        mLabelClickListener = l;    }    /**     * 设置标签的选择监听     *     * @param l     */    public void setOnLabelSelectChangeListener(OnLabelSelectChangeListener l) {        mLabelSelectChangeListener = l;    }    /**     * sp转px     */    public static int sp2px(Context context, float spVal) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,                spVal, context.getResources().getDisplayMetrics());    }    public interface OnLabelClickListener {        void onLabelClick(View label, String labelText, int position);    }    public interface OnLabelSelectChangeListener {        void onLabelSelectChange(View label, String labelText, boolean isSelect, int position);    }}

布局

    <LabelsView        xmlns:app="http://schemas.android.com/apk/res-auto"       android:id="@+id/labels"       android:layout_width="match_parent"       android:layout_height="wrap_content"       app:labelBackground="@drawable/label_bg"     //标签的背景       app:labelTextColor="@drawable/label_text_color" //标签的字体颜色 可以是一个颜色值       app:labelTextSize="14sp"      //标签的字体大小       app:labelTextPaddingBottom="5dp"   //标签的上下左右边距       app:labelTextPaddingLeft="10dp"       app:labelTextPaddingRight="10dp"       app:labelTextPaddingTop="5dp"       app:lineMargin="10dp"   //行与行的距离       app:wordMargin="10dp"   //标签与标签的距离       app:selectType="SINGLE"   //标签的选择类型 有单选、多选、不可选三种类型       app:maxSelect="5" />  //标签的最大选择数量,只有多选的时候才有用,0为不限数量

监听

//标签的点击监听labelsView.setOnLabelClickListener(new LabelsView.OnLabelClickListener() {    @Override    public void onLabelClick(View label, String labelText, int position) {         //label是被点击的标签,labelText是标签的文字,position是标签的位置。    }});//标签的选中监听labelsView.setOnLabelSelectChangeListener(new LabelsView.OnLabelSelectChangeListener() {    @Override    public void onLabelSelectChange(View label, String labelText, boolean isSelect, int position) {        //label是被点击的标签,labelText是标签的文字,isSelect是是否选中,position是标签的位置。    }});

常用方法

//设置选中标签。//positions是个可变类型,表示被选中的标签的位置。//比喻labelsView.setSelects(1,2,5);选中第1,3,5个标签。如果是单选的话,只有第一个参数有效。public void setSelects(int... positions);//获取选中的标签。返回的是一个Integer的数组,表示被选中的标签的下标。如果没有选中,数组的size等于0。public ArrayList<Integer> getSelectLabels();//取消所有选中的标签。public void clearAllSelect();//设置标签的选择类型,有NONE、SINGLE和MULTI三种类型。public void setSelectType(SelectType selectType);//设置最大的选择数量,只有selectType等于MULTI是有效。public void setMaxSelect(int maxSelect);//设置标签背景public void setLabelBackgroundResource(int resId);//设置标签的文字颜色public void setLabelTextColor(int color);public void setLabelTextColor(ColorStateList color);//设置标签的文字大小(单位是px)public void setLabelTextSize(float size);//设置标签内边距public void setLabelTextPadding(int left, int top, int right, int bottom);//设置行间隔public void setLineMargin(int margin);//设置标签的间隔public void setWordMargin(int margin);

代码来自 博客:donkingliang,本人微改后使用,效果不错,感谢donkingliang!

原创粉丝点击