Android中标签TagLayout支持单选多选

来源:互联网 发布:e盾网络验证价格 编辑:程序博客网 时间:2024/05/16 09:44


首先给出主控件主要代码

public class TagLayout extends ViewGroup {    private static final int DEFAULT_TAG_RES_ID = R.layout.item_tag;    private static final int SELECT_MODE_NONE = 0;    private static final int SELECT_MODE_SINGLE = 1;    private static final int SELECT_MODE_MULTIPLE = 2;    private int mTagSelectMode = SELECT_MODE_NONE;    private Integer mTagTextSize;    private int mTagResId = DEFAULT_TAG_RES_ID;    private List<TagLine> mTagLines = new ArrayList<>();    private int mHorizontalSpace = 0;    private int mVerticalSpace = 0;    private int maxLines = Integer.MAX_VALUE;    private List<String> mTags;    private LayoutInflater mInflater;    private Integer mTagBackground;    private Integer mTagMinWidth;    private ColorStateList mTagTextColor;    private Integer mTagTextHorizontalPadding;    private Integer mTagTextVerticalPadding;    private static final int DEFAULT_CACHE_LINES = 3;    private TextView mCurrentSelected;    private boolean mHasMeasured = false;    private int mLastWidthMeasureSpec;    private int mLastHeightMeasureSpec;    private int mLastMeasureWidth;    private int mLstMeasureHeight;    public interface OnSelectChangeListener {        void onSelectChange(TextView child, int index, boolean isSelected);    }    public interface OnItemClickListener {        void onItemClick(TextView child, int index);    }    private OnSelectChangeListener onSelectChangeListener;    private OnItemClickListener onItemClickListener;    public void setOnSelectChangeListener(OnSelectChangeListener onSelectChangeListener) {        this.onSelectChangeListener = onSelectChangeListener;    }    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {        this.onItemClickListener = onItemClickListener;    }    public TagLayout(Context context) {        super(context);        mInflater = LayoutInflater.from(context);    }    public TagLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mInflater = LayoutInflater.from(context);        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TagLayout);        if (a != null) {            mHorizontalSpace = a.getDimensionPixelOffset(R.styleable.TagLayout_horizontalSpace, 0);            mVerticalSpace = a.getDimensionPixelOffset(R.styleable.TagLayout_verticalSpace, 0);            maxLines = a.getInteger(R.styleable.TagLayout_maxLines, Integer.MAX_VALUE);            mTagResId = a.getResourceId(R.styleable.TagLayout_tagResId, DEFAULT_TAG_RES_ID);            if (a.hasValue(R.styleable.TagLayout_tagTextSize)) {                mTagTextSize = a.getDimensionPixelSize(R.styleable.TagLayout_tagTextSize, 0);            }            if (a.hasValue(R.styleable.TagLayout_tagBackground)) {                mTagBackground = a.getResourceId(R.styleable.TagLayout_tagBackground, -1);            }            if (a.hasValue(R.styleable.TagLayout_tagTextColor)) {                mTagTextColor = a.getColorStateList(R.styleable.TagLayout_tagTextColor);            }            if (a.hasValue(R.styleable.TagLayout_tagTextHorizontalPadding)) {                mTagTextHorizontalPadding = a.getDimensionPixelOffset(R.styleable.TagLayout_tagTextHorizontalPadding, 0);            }            if (a.hasValue(R.styleable.TagLayout_tagTextVerticalPadding)) {                mTagTextVerticalPadding = a.getDimensionPixelOffset(R.styleable.TagLayout_tagTextVerticalPadding, 0);            }            if (a.hasValue(R.styleable.TagLayout_tagSelectMode)) {                mTagSelectMode = a.getInt(R.styleable.TagLayout_tagSelectMode, SELECT_MODE_NONE);            }            if (a.hasValue(R.styleable.TagLayout_tagMinWidth)) {                mTagMinWidth = a.getDimensionPixelOffset(R.styleable.TagLayout_tagMinWidth, 0);            }            a.recycle();        }        if (maxLines <= DEFAULT_CACHE_LINES) {            int maxWidth = ViewUtils.getDisplayWidth();            for (int i = 0; i < maxLines; i++) {                int totalChildSizeWidth = 0;                while (totalChildSizeWidth < maxLines) {                    TextView tagView = addTag(" ");                    tagView.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST));                    tagView.setVisibility(View.INVISIBLE);                    totalChildSizeWidth += tagView.getMeasuredWidth() + mHorizontalSpace;                }            }        }    }    private TextView addTag(final String tagText) {        final TextView tagView = (TextView) mInflater.inflate(mTagResId, null);        if (hasValue(mTagBackground)) {            tagView.setBackgroundResource(mTagBackground);        }        if (hasValue(mTagTextSize)) {            tagView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTagTextSize);        }        if (hasValue(mTagTextColor)) {            tagView.setTextColor(mTagTextColor);        }        if (hasValue(mTagMinWidth)) {            tagView.setMinWidth(mTagMinWidth);        }        int paddingLeft = tagView.getPaddingLeft();        int paddingRight = tagView.getPaddingRight();        int paddingTop = tagView.getPaddingTop();        int paddingBottom = tagView.getPaddingBottom();        if (hasValue(mTagTextHorizontalPadding)) {            paddingLeft = mTagTextHorizontalPadding;            paddingRight = mTagTextHorizontalPadding;        }        if (hasValue(mTagTextVerticalPadding)) {            paddingTop = mTagTextVerticalPadding;            paddingBottom = mTagTextVerticalPadding;        }        tagView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);        tagView.setText(tagText);        final int position = getChildCount();        tagView.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (tagView.getVisibility() != View.VISIBLE)                    return;                if (onItemClickListener != null) {                    onItemClickListener.onItemClick(tagView, position);                }                if (mTagSelectMode == SELECT_MODE_MULTIPLE) {                    tagView.setSelected(!tagView.isSelected());                    if (onSelectChangeListener != null) {                        onSelectChangeListener.onSelectChange(tagView, position, tagView.isSelected());                    }                } else if (mTagSelectMode == SELECT_MODE_SINGLE) {                    if (mCurrentSelected != null) {                        mCurrentSelected.setSelected(false);                    }                    tagView.setSelected(true);                    mCurrentSelected = tagView;                    if (onSelectChangeListener != null) {                        onSelectChangeListener.onSelectChange(tagView, position, tagView.isSelected());                    }                }            }        });        addView(tagView);        return tagView;    }    private boolean hasValue(Object value) {        return value != null;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int parentSuggestWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);        if (mHasMeasured && mLastWidthMeasureSpec == widthMeasureSpec && mLastHeightMeasureSpec == heightMeasureSpec) {            setMeasuredDimension(mLastMeasureWidth, mLstMeasureHeight);            return;        }        mTagLines.clear();        TagLine tagLine = null;        int maxWidth = parentSuggestWidth - getPaddingLeft() - getPaddingRight();        for (int i = 0; i < getChildCount(); i++) {            View child = getChildAt(i);            if (child.getVisibility() == View.GONE) {                continue;            }            measureChild(child, widthMeasureSpec, heightMeasureSpec);            if (tagLine == null) {                tagLine = newTagLine(maxWidth);                tagLine.addView(child);            } else {                if (tagLine.accept(child)) {                    tagLine.addView(child);                } else {                    if (mTagLines.size() == maxLines) {                        for (int hiddenIndex = i; hiddenIndex < getChildCount(); hiddenIndex++) {                            getChildAt(hiddenIndex).setVisibility(View.GONE);                        }                        break;                    }                    tagLine = newTagLine(maxWidth);                    tagLine.addView(child);                }            }        }        int measureHeight = getPaddingTop() + getPaddingBottom();        for (int i = 0; i < mTagLines.size(); i++) {            measureHeight += mTagLines.get(i).height;            if (i != mTagLines.size() - 1) {                measureHeight += mVerticalSpace;            }        }        setMeasuredDimension(mLastMeasureWidth = parentSuggestWidth, mLstMeasureHeight = resolveSize(measureHeight, heightMeasureSpec));        mLastWidthMeasureSpec = widthMeasureSpec;        mLastHeightMeasureSpec = heightMeasureSpec;        mHasMeasured = true;    }    public void setTags(List<String> tagsList) {        mHasMeasured = false;        if (this.mTags == tagsList) {            return;        }        if (maxLines <= DEFAULT_CACHE_LINES || tagsList.size() <= getChildCount()) {//使用缓存            for (int i = 0; i < getChildCount(); i++) {                TextView tagView = (TextView) getChildAt(i);                tagView.setVisibility(View.GONE);            }            if (tagsList != null && tagsList.size() > 0) {                int visibleChildCount = Math.min(tagsList.size(), getChildCount());                for (int i = 0; i < visibleChildCount; i++) {                    TextView tagView = (TextView) getChildAt(i);                    tagView.setVisibility(View.VISIBLE);                    final String tagText = tagsList.get(i);                    tagView.setText(tagText);                }            }        } else {//删除 再添加            if (mTags != null && mTags.size() > 0) {                mTags.clear();            }            removeAllViews();            if (tagsList != null && tagsList.size() > 0) {                for (int i = 0; i < tagsList.size(); i++) {                    addTag(tagsList.get(i));                }            }        }    }    public List<Integer> getSelectedTagPositions() {        List<Integer> selectedList = new ArrayList<>();        if (mTagSelectMode == SELECT_MODE_SINGLE && mCurrentSelected != null) {            selectedList.add(indexOfChild(mCurrentSelected));        } else {            for (int i = 0; i < getChildCount(); i++) {                if (getChildAt(i).getVisibility() == View.VISIBLE && getChildAt(i).isSelected()) {                    selectedList.add(i);                }            }        }        return selectedList;    }    private TagLine newTagLine(int maxWidth) {        TagLine tagLine = new TagLine(maxWidth, mHorizontalSpace);        mTagLines.add(tagLine);        return tagLine;    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int marginTop = getPaddingTop();        int marginLeft = getPaddingLeft();        for (int i = 0; i < mTagLines.size(); i++) {            TagLine line = mTagLines.get(i);            line.layout(marginLeft, marginTop);            marginTop += mVerticalSpace + line.height;        }    }    public class TagLine {        private List<View> mTagViews = new ArrayList<>();        private int totalWidth;        private int space;        private int usedWidth;        private int height;        public TagLine(int totalWidth, int horizontalSpace) {            this.totalWidth = totalWidth;            this.space = horizontalSpace;        }        public void addView(View child) {            int childWidth = child.getMeasuredWidth();            int childHeight = child.getMeasuredHeight();            if (mTagViews.size() == 0) {                if (childWidth > totalWidth) {                    usedWidth = totalWidth;                    height = childHeight;                } else {                    usedWidth = childWidth;                    height = childHeight;                }            } else {                usedWidth = usedWidth + space + childWidth;                height = (childHeight > height) ? childHeight : height;            }            mTagViews.add(child);        }        public boolean accept(View child) {            int width = child.getMeasuredWidth();            if (mTagViews.size() == 0) {                return true;            }            if (usedWidth + width + space > totalWidth) {                return false;            }            return true;        }        public void layout(int marginLeft, int marginTop) {            for (int i = 0; i < mTagViews.size(); i++) {                View child = mTagViews.get(i);                int childWidth = child.getMeasuredWidth();                int childHeight = child.getMeasuredHeight();                int extraTop = (int) ((height - childHeight) / 2f + 0.5f);                int left = marginLeft;                int top = marginTop + extraTop;                int right = left + childWidth;                int bottom = top + childHeight;                child.layout(left, top, right, bottom);                marginLeft += childWidth + space;            }        }    }}
然后在自定义的attrs.xml中增加

<declare-styleable name="TagLayout">    <attr name="horizontalSpace" format="dimension" /><!-- tag之间的间距-->    <attr name="verticalSpace" format="dimension" /><!-- tag之间的间距-->    <attr name="maxLines" format="integer" /><!-- 最大行数-->    <attr name="tagResId" format="reference" /><!-- tag布局的资源id-->    <attr name="tagTextSize" format="dimension" /><!-- tag文字大小-->    <attr name="tagBackground" format="reference" /><!-- tag背景-->    <attr name="tagMinWidth" format="dimension" /><!-- tag最小宽度-->    <attr name="tagTextColor" format="color" /><!-- tag文字颜色-->    <attr name="tagTextHorizontalPadding" format="dimension" /><!-- tag 内部padding-->    <attr name="tagTextVerticalPadding" format="dimension" /><!-- tag 内部padding-->    <attr name="tagSelectMode" format="enum"><!-- 单选 多选-->        <enum name="single" value="1"></enum>        <enum name="multiple" value="2"></enum>        <enum name="none" value="0"></enum>    </attr></declare-styleable>


上面R.layout.item_tag.xml就是添加的item的布局

<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:gravity="center"    ></TextView>

通过上面的<declare-styleable name="TagLayout">很容易看出来用法下面就是布局中的用法 

<android:id="@+id/mTags"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:paddingRight="@dimen/w29"    android:paddingLeft="@dimen/w29"    android:paddingTop="@dimen/w29"    android:paddingBottom="@dimen/w29"    app:horizontalSpace="@dimen/w29"    app:verticalSpace="@dimen/w29"    app:tagTextColor="@color/selector_skill_tag_text"    app:tagBackground="@drawable/selector_skill_tag"    app:tagTextHorizontalPadding="@dimen/w22"    app:tagTextVerticalPadding="@dimen/w13"    app:tagMinWidth="@dimen/w142"    app:tagSelectMode="single"/>

可以看到app开头的都是在attrs.xml中定义的了 所以自己加什么属性 可以更具项目自己配置

上面是整个TagLayout 的代码 

············································································

下面就是整个Taglayout的在Activity中的使用

mTags=(TagLayout)findViewById(R.id.mTags);//找到控件List<String> tags = new ArrayList<>();for (int i = 0; i < 10; i++) {    tags.add(String.valueOf(i));}mTags.setTags(tags);//将标签添加到mTags.setOnSelectChangeListener(new TagLayout.OnSelectChangeListener() {    @Override    public void onSelectChange(TextView child, int index, boolean isSelected) {        if(isSelected){            String text=child.getText();        }    }});


上面的代码就是你所选中的文字 还有很多需要自己看



1 0
原创粉丝点击