Android標簽流控件的實現
我們從服務器端獲取標簽的信息,然后將其動態的添加到布局中,并且我們能夠得到我們選擇容器的信息,并將選中的標簽重新返回至服務器。
前言
在我們的開發過程中,常常會遇到這樣的場景:
我們展示一種物品或者為某一事物添加一些標簽。比如說,我們買一件衣服,可以有以下幾種標簽:杰克瓊斯,男士,運動等等。
但我們這時候可能并不知道標簽的數量和每個標簽的文字,所以,我們在開發過程中,需要實現下面的功能:
我們從服務器端獲取標簽的信息,然后將其動態的添加到布局中,并且我們能夠得到我們選擇容器的信息,并將選中的標簽重新返回至服務器。
因此,我們必須計算出每個標簽(Button)的長度,并且將其與它的容器做比較,如果容器剩余的長度并不足以容納一個標簽的時候,那么就會另起一行,添加標簽,就這樣周而復始,直到所有的標簽添加到容器中。
實現
我們將我們自定義的控件命名為TagCloudLayout,它繼承ViewGroup 并將它作為標簽的容器。同時覆寫onMeasure()和onLayout方法
onMeasure()方法
通過覆寫onMeasure()方法,我們可以計算出容器和各標簽的長度和寬度,代碼如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int wantHeight = 0; int wantWidth = resolveSize(0, widthMeasureSpec);int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); int childLeft = paddingLeft; int childTop = paddingTop; int lineHeight = 0; for (int i = 0; i < getChildCount(); i++) { final View childView = getChildAt(i); if (childView.getVisibility() == View.GONE) { continue; } LayoutParams params = childView.getLayoutParams(); childView.measure( getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, params.width), getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, params.height) ); int childHeight = childView.getHeight(); int childWidth = childView.getWidth(); lineHeight = Math.max(childHeight, lineHeight); if (childLeft + childWidth + paddingRight > wantWidth) { childLeft = paddingLeft; childTop += mLineSpacing + childHeight; lineHeight = childHeight; } else { childLeft += childWidth + mTagSpacing; } } wantHeight = childTop + lineHeight + paddingBottom; setMeasuredDimension(wantWidth, resolveSize(wantHeight, heightMeasureSpec)); }</pre> <h3>onLayout()方法 </h3>
計算好長度和寬度之后,我們就可以進行布局了。
protected void onLayout(boolean changed, int l, int t, int r, int b) { int width = r - l;int paddingLeft = getPaddingLeft(); int paddingTop = getPaddingTop(); int paddingRight = getPaddingRight(); int childLeft = paddingLeft; int childTop = paddingTop; int lineHeight = 0; for (int i = 0, childCount = getChildCount(); i < childCount; ++i) { final View childView = getChildAt(i); if (childView.getVisibility() == View.GONE) { continue; } int childWidth = childView.getMeasuredWidth(); int childHeight = childView.getMeasuredHeight(); lineHeight = Math.max(childHeight, lineHeight); if (childLeft + childWidth + paddingRight > width) { childLeft = paddingLeft; childTop += mLineSpacing + lineHeight; lineHeight = childHeight; } childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childLeft += childWidth + mTagSpacing; }
}</pre>
在主應用程序調用
這樣的話,我們的控件的主要方法就完成了,接下來我們就可以在主應用程序中直接調用了,代碼如下:
TagCloudLayout mContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.test_btn); mContainer = (TagCloudLayout) findViewById(R.id.container); ArrayList<String> list = new ArrayList<>(); list.add("one"); list.add("你好"); list.add("three"); list.add("four"); list.add("ninkfnsadf"); list.add("fsadfsdgdsfasd"); list.add("fasdgsdagfsdafdsfsadfsadf"); list.add("adf"); list.add("one"); list.add("fasdfadfa"); list.add("fads"); list.add("中國"); list.add("one"); list.add("柴靜"); list.add("three"); list.add("four"); mContainer.addData(list); mContainer.drawLayout(); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });}</pre>
效果
最后,讓我們來看看實現效果
![]()
結束語
這個自定義控件我感覺還是挺實用的,所以我會抽出時間將它整理,便于他人調用,項目的地址是標簽云控件,歡迎大家指正。
參考資料
</div> 來自:http://www.fyales.com/archives/71
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!