版權聲明:本文爲博主原創文章,未經博主容許不得轉載。前端
不管是在移動端的App,仍是在前端的網頁,咱們常常會看到下面這種標籤的列表效果:
標籤從左到右擺放,一行顯示不下時自動換行。這樣的效果用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; }
標籤的擺放: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()); } }
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" /> //標籤與標籤的距離
二、設置標籤: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);
三、設置點擊監聽:(若是須要的話)微信
labels.setOnLabelClickListener(new LabelsView.OnLabelClickListener() { @Override public void onLabelClick(TextView label, int position) { //label就是被點擊的標籤,position就是標籤的位置。 } });
效果圖: markdown
使用前不要忘了引入依賴:微信開發
allprojects {
repositories {
... maven { url 'https://jitpack.io' } } } dependencies { compile 'com.github.donkingliang:LabelsView:1.0.0' }
最後給出該控件在GitHub中的地址,歡迎你們訪問和使用。
https://github.com/donkingliang/LabelsViewapp
文章已同步到個人簡書maven