无论是在移动端的App,还是在前端的网页,我们经常会看到下面这种标签的列表效果:

标签列表

标签从左到右摆放,一行显示不下时自动换行。这样的效果用Android源生的控件很不好实现,所以往往需要我们自己去自定义控件。我在开发中就遇到过几次要实现这样的标签列表效果,所以就自己写了个控件,放到我的GitHub,方便以后使用。有兴趣的同学也欢迎访问我的GitHub、查看源码实现和使用该控件。下面我将为大家介绍该控件的具体实现和使用。
要实现这样一个标签列表其实并不难,列表中的item可以直接用TextView来实现,我们只需要关心列表控件的大小和标签的摆放就可以了。也就是说我们需要做的只要两件事:测量布局(onMeasure)和摆放标签(onLayout)。这是自定义ViewGroup的基本步骤,相信对自定义View有所了解的同学都不会陌生。下面我们就来看看具体的代码实现。
控件的测量:

    @Overrideprotected 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; //是否是行的开头//循环测量item并计算控件的内容宽高for (int i = 0; i < count; i++) {View view = getChildAt(i);measureChild(view, widthMeasureSpec, heightMeasureSpec);if(!begin) {lineWidth += mWordMargin;}else {begin = false;}//当前行显示不下item时换行。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());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);}}//这一句是为了支持minWidth属性。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);}}//这一句是为了支持minHeight属性。result = Math.max(result, getSuggestedMinimumHeight());return result;}

标签的摆放:

    @Overrideprotected 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();//循环摆放itemfor (int i = 0; i < count; i++) {View view = getChildAt(i);//当前行显示不下item时换行。if (contentWidth < x + view.getMeasuredWidth() + getPaddingRight()) {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());}}

onMeasure和onLayout的实现代码基本是一样的,不同的只是一个是测量宽高,一个是摆放位置而已。实现起来非常的简单。
以上是LabelsView的核心代码,LabelsView除了实现了item的测量和摆放以外,还提供了一系列的方法让使用者可以方便设置标签的样式(包括标签被选中的样式)和标签点击、选中的监听等。下面LabelsView的使用介绍。

1、引入依赖
在Project的build.gradle在添加以下代码

allprojects {repositories {...maven { url 'https://jitpack.io' }}
}

在Module的build.gradle在添加以下代码

dependencies {compile 'com.github.donkingliang:LabelsView:1.4.1'
}

2、编写布局:

   <com.donkingliang.labels.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为不限数量

这里有两个地方需要说明一下:

1)标签的正常样式和选中样式是通过drawable来实现的。比如下面两个drawable。

<!-- 标签的背景 label_bg -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"><!-- 标签选中时的背景 --><item android:state_selected="true"><shape><stroke android:width="2dp" android:color="#fb435b" /><corners android:radius="8dp" /><solid android:color="@android:color/white" /></shape></item><!-- 标签的正常背景 --><item><shape><stroke android:width="2dp" android:color="#656565" /><corners android:radius="8dp" /><solid android:color="@android:color/white" /></shape></item>
</selector>
<!-- 标签的文字颜色 label_text_color -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"><!-- 标签选中时的文字颜色 --><item android:color="#fb435b" android:state_selected="true" /><!-- 标签的正常文字颜色 --><item android:color="#2d2b2b" />
</selector>

TextView的textColor属性除了可以设置一个颜色值以外,也可以通过资源来设置的,这一点很多同学都不知道。

2)标签的选择类型有四种:

NONE :标签不可选中,也不响应选中事件监听,这是默认值。

SINGLE:单选(可反选)。这种模式下,可以一个也不选。

SINGLE_IRREVOCABLY:单选(不可反选)。这种模式下,有且只有一个是选中的。默认是第一个。

MULTI:多选,可以通过设置maxSelect限定选择的最大数量,0为不限数量。maxSelect只有在多选的时候才有效。多选模式下可以设置一些标签为必选项。必选项的标签默认选中,且不能取消。

3、设置标签:

labelsView = (LabelsView) findViewById(labels);
ArrayList<String> label = new ArrayList<>();
label.add("Android");
label.add("IOS");
label.add("前端");
label.add("后台");
label.add("微信开发");
label.add("游戏开发");
labelsView.setLabels(label); //直接设置一个字符串数组就可以了。//LabelsView可以设置任何类型的数据,而不仅仅是String。
ArrayList<TestBean> testList = new ArrayList<>();
testList.add(new TestBean("Android",1));
testList.add(new TestBean("IOS",2));
testList.add(new TestBean("前端",3));
testList.add(new TestBean("后台",4));
testList.add(new TestBean("微信开发",5));
testList.add(new TestBean("游戏开发",6));
labelsView.setLabels(testList, new LabelsView.LabelTextProvider<TestBean>() {@Overridepublic CharSequence getLabelText(TextView label, int position, TestBean data) {//根据data和position返回label需要显示的数据。return data.getName();}
});

4、设置事件监听:(如果需要的话)

//标签的点击监听
labelsView.setOnLabelClickListener(new LabelsView.OnLabelClickListener() {@Overridepublic void onLabelClick(TextView label, Object data, int position) {//label是被点击的标签,data是标签所对应的数据,position是标签的位置。}
});
//标签的选中监听
labelsView.setOnLabelSelectChangeListener(new LabelsView.OnLabelSelectChangeListener() {@Overridepublic void onLabelSelectChange(TextView label, Object data, boolean isSelect, int position) {//label是被选中的标签,data是标签所对应的数据,isSelect是是否选中,position是标签的位置。}
});

5、常用方法

//设置选中标签。
//positions是个可变类型,表示被选中的标签的位置。
//比喻labelsView.setSelects(1,2,5);选中第1,3,5个标签。如果是单选的话,只有第一个参数有效。
public void setSelects(int... positions);
public void setSelects(List<Integer> positions);//获取选中的标签(返回的是所有选中的标签的位置)。返回的是一个Integer的数组,表示被选中的标签的下标。如果没有选中,数组的size等于0。
public ArrayList<Integer> getSelectLabels();
//获取选中的label(返回的是所有选中的标签的数据)。如果没有选中,数组的size等于0。T表示标签的数据类型。
public <T> List<T> getSelectLabelDatas();//取消所有选中的标签。
public void clearAllSelect();//设置标签的选择类型,有NONE、SINGLE、SINGLE_IRREVOCABLY和MULTI四种类型。
public void setSelectType(SelectType selectType);//设置最大的选择数量,只有selectType等于MULTI是有效。
public void setMaxSelect(int maxSelect);//设置必选项,只有在多项模式下,这个方法才有效
public void setCompulsorys(int... positions)
public void setCompulsorys(List<Integer> positions)//清空必选项,只有在多项模式下,这个方法才有效
public void clearCompulsorys()//设置标签背景
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);

所有的set方法都有对应的get方法,这里就不说了。

效果图:

效果图.gif

最后给出该控件在GitHub中的地址,欢迎大家访问和使用。
https://github.com/donkingliang/LabelsView

作者:donkingliang
链接:https://www.jianshu.com/p/c574b763e264
來源:简书

android 自定义标签选项相关推荐

  1. android ui 扁平化,android 自定义标签的使用,实现扁平化UI设计

    2014年8月6日11:06:44 android对自定义标签的使用,实现扁平化UI设计: 1.attrs.xml文件中自定义标签 如: //reference指的是是从string.xml引用过来 ...

  2. Android自定义标签列表控件LabelsView

    无论是在移动端的App,还是在前端的网页,我们经常会看到下面这种标签的列表效果: 标签从左到右摆放,一行显示不下时自动换行.这样的效果用Android源生的控件很不好实现,所以往往需要我们自己去自定义 ...

  3. Android自定义标签列表控件LabelsView解析

    无论是在移动端的App,还是在前端的网页,我们经常会看到下面这种标签的列表效果: 标签从左到右摆放,一行显示不下时自动换行.这样的效果用Android源生的控件很不好实现,所以往往需要我们自己去自定义 ...

  4. android 自定义标签导航栏,自定义导航栏app下载-自定义导航栏(Custom Navigation Bar) 安卓版v0.4.3-PC6安卓网...

    自定义导航栏(Custom Navigation Bar)app是款非常好用的实用工具,自定义导航栏能让你自己设置个性的导航栏,再也不用为单调的导航栏而发愁,独特且唯一,感兴趣的朋友就来下载自定义导航 ...

  5. android 如何去掉自定义标签页,Android中为TextView增加自定义的HTML标签

    Android中的TextView,本身就支持部分的Html格式标签.这其中包括常用的字体大小颜色设置,文本链接等.使用起来也比较方便,只需要使用Html类转换一下即可.比如: textView.se ...

  6. android学习笔记---66_自定义标签页

    2013/7/17 66_自定义标签页 技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:___________以前的网站现在不弄了,抱歉 smdl2tmp1. ...

  7. android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...

    转载:http://blog.csdn.net/xiabing082/article/details/48781489 1.  大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...

  8. Android Activity标签属性

    Android Activity标签属性 Activity 是 Android 系统四大应用组件之一,用户可与 Activity 提供的屏幕进行交互,以执行拨打电话.拍摄照片.发送电子邮件等操作开发者 ...

  9. chrome自定义背景_Android Chrome自定义标签

    chrome自定义背景 In this tutorial, we'll be discussing and implementing Chrome Custom Tabs in our Android ...

最新文章

  1. Keras正式从TensorFlow分离:结束API混乱与耗时编译
  2. Jquery Types 小结
  3. DDD China Conference 2017
  4. 给Xshell设置舒适的配色方案
  5. 点云网络的论文理解(六)-Frustum PointNets 总体概括
  6. 神经网络第三部分:网络Neural Networks, Part 3: The Network
  7. python socket服务器多线程_Python多线程socket服务器端
  8. ubuntu每日构建版
  9. 世界杯足球竞赛源码下载
  10. 昨天,面试了一个安全工程师,她的回答让我耳目一新
  11. 51单片机学习笔记【九】——红外通信实验
  12. 服务器删除东西直接找不到了,重新安装T1后,用了一天半,又出现演示版到期的问题了-重新删除T1PFLS服务后,怎么找不到服务器-esrv-Gh....exe文件?...
  13. 读nandflash---根据数据手册K9GAG08U0D
  14. 电脑网页出现服务器异常 请刷新页面重试,无法打开网页请尝试刷新页面是怎么回事?网页无法打开是什么原因...
  15. 加快onenote同步速度
  16. 《线性代数:行列式》: 克拉默法则
  17. 六、T100固定资产之固定资产月结处理
  18. android—AOSP、AOKP、CM的区别
  19. 自己用的停用词(2955个)
  20. 立体仓库货物识别率99.9%!AI让仓储管理事半功倍

热门文章

  1. 关闭 matplotlib 横纵坐标
  2. word计算机时间,【2017年职称计算机考试word2003考点输入日期和时间】- 环球网校...
  3. [华语音乐]纪念家驹逝世16周年《46张专辑+单曲》[MP3!]
  4. python如何设计工具类_Python基础之自定义工具类
  5. C#操作IIS创建应用程序池出现异常:无效索引(Exception from HRESULT:0x80070585)
  6. RxJava2总结之操作详解(三)
  7. Swift输入框过滤表情
  8. 一岁一礼 一寸欢喜 | 三分尽兴 七分惊喜 | 齐飞20了
  9. java学习input_1
  10. 如何不花一分钱在百度科技园过三天