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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!