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

不管是在移动端的App,仍是在前端的网页,咱们常常会看到下面这种标签的列表效果: 
标签列表1 
标签列表2 
标签从左到右摆放,一行显示不下时自动换行。这样的效果用Android源生的控件很很差实现,因此每每须要咱们本身去自定义控件。我在开发中就遇到过几回要实现这样的标签列表效果,因此就本身写了个控件,放到个人GitHub,方便之后使用。有兴趣的同窗也欢迎访问个人GitHub、查看源码实现和使用该控件。下面我将为你们介绍该控件的具体实现和使用。 
要实现这样一个标签列表其实并不难,列表中的item能够直接用TextView来实现,咱们只须要关心列表控件的大小和标签的摆放就能够了。也就是说咱们须要作的只要两件事:测量布局(onMeasure)和摆放标签(onLayout)。这是自定义ViewGroup的基本步骤,相信对自定义View有所了解的同窗都不会陌生。下面咱们就来看看具体的代码实现。 
控件的测量:java

@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; //是不是行的开头 //循环测量item并计算控件的内容宽高 for (int i = 0; i < count; i++) { View view = getChildAt(i); measureChild(view, widthMeasureSpec, heightMeasureSpec); //当前行显示不下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()); 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); } } //这一句是为了支持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; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

标签的摆放:android

@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(); //循环摆放item for (int i = 0; i < count; i++) { View view = getChildAt(i); //当前行显示不下item时换行。 if (contentWidth < x + view.getMeasuredWidth()) { 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()); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

onMeasure和onLayout的实现代码基本是同样的,不一样的只是一个是测量宽高,一个是摆放位置而已。实现起来很是的简单。 
控件的使用就更加的简单了,只须要三步: 
一、编写布局:git

<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/pink_frame_bg" //标签的背景 app:labelTextColor="#fb435b" //标签的字体颜色 app:labelTextSize="14sp" //标签的字体大小 app:labelTextPaddingBottom="5dp" //标签的上下左右边距 app:labelTextPaddingLeft="10dp" app:labelTextPaddingRight="10dp" app:labelTextPaddingTop="5dp" app:lineMargin="10dp" //行与行的距离 app:wordMargin="10dp" /> //标签与标签的距离
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

二、设置标签:github

ArrayList<String> list = new ArrayList<>(); list.add("Android"); list.add("IOS"); list.add("前端"); list.add("后台"); list.add("微信开发"); list.add("Java"); list.add("JavaScript"); list.add("C++"); list.add("PHP"); list.add("Python"); labelsView.setLabels(list);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

三、设置点击监听:(若是须要的话)微信

labels.setOnLabelClickListener(new LabelsView.OnLabelClickListener() { @Override public void onLabelClick(TextView label, int position) { //label就是被点击的标签,position就是标签的位置。 } });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果图: 
效果图markdown

使用前不要忘了引入依赖:微信开发

allprojects {
        repositories {
            ... maven { url 'https://jitpack.io' } } } dependencies { compile 'com.github.donkingliang:LabelsView:1.0.0' }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

文章已同步到个人简书maven

相关文章
相关标签/搜索