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
- Android中标签TagLayout支持单选多选
- Android中标签TextView的使用
- Android Tween Animation XML文件中标签的使用
- 【Android】修改Tablayout中标签文字的样式
- Struts2中标签问题
- 去除html中标签
- 扩展Fckeditor2.6.4中标签使其支持把标签体的内容作为编辑器默认值
- struts中标签的用法
- Dreamweaver中标签大小写转换
- jsp中标签的引用
- JSF中标签的使用
- Struts中标签的引入
- HTML中标签的使用
- Java中标签的使用
- AOP中标签加载通知
- 解析JSP中标签库
- css中标签的定义
- 去除html中标签方法
- Android内存优化方案和内存泄露检测分析方法
- RMQ<区间最值查找,O(n*logn)
- android 小米手机API兼容问题解决思路
- Linux进程间通信——使用流套接字
- 浓缩的才是精华:浅析GIF格式图片的存储和压缩
- Android中标签TagLayout支持单选多选
- CentOS7最小安装之后安装xfce桌面
- Angular之控制器篇
- 罗斯基白话:TensorFlow+实战系列(四)变量管理
- 关于html 中div 填满另一个div
- 项目记录-处理两个相交圆方法探索3
- mysql 导入导出
- go单元测试进阶篇
- 线索二叉树的遍历与基本操作(史上最全)