标签:
原文地址
在我们的开发过程中,常常会遇到这样的场景:
我们展示一种物品或者为某一事物添加一些标签。比如说,我们买一件衣服,可以有以下几种标签:杰克琼斯,男士,运动等等。
但我们这时候可能并不知道标签的数量和每个标签的文字,所以,我们在开发过程中,需要实现下面的功能:
我们从服务器端获取标签的信息,然后将其动态的添加到布局中,并且我们能够得到我们选择容器的信息,并将选中的标签重新返回至服务器。
因此,我们必须计算出每个标签(Button)的长度,并且将其与它的容器做比较,如果容器剩余的长度并不足以容纳一个标签的时候,那么就会另起一行,添加标签,就这样周而复始,直到所有的标签添加到容器中。
我们将我们自定义的控件命名为TagCloudLayout,它继承ViewGroup 并将它作为标签的容器。同时覆写onMeasure()和onLayout方法
通过覆写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));
}
计算好长度和宽度之后,我们就可以进行布局了。
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;
}
}
这样的话,我们的控件的主要方法就完成了,接下来我们就可以在主应用程序中直接调用了,代码如下:
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) {
}
});
}
最后,让我们来看看实现效果
这个自定义控件我感觉还是挺实用的,所以我会抽出时间将它整理,便于他人调用,项目的地址是标签云控件,欢迎大家指正。
标签:
原文地址:http://my.oschina.net/weiCloudS/blog/382689