码迷,mamicode.com
首页 > 其他好文 > 详细

标签流控件的实现

时间:2015-03-04 22:53:40      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

前言

原文地址
在我们的开发过程中,常常会遇到这样的场景:

我们展示一种物品或者为某一事物添加一些标签。比如说,我们买一件衣服,可以有以下几种标签:杰克琼斯,男士,运动等等。

但我们这时候可能并不知道标签的数量和每个标签的文字,所以,我们在开发过程中,需要实现下面的功能:

我们从服务器端获取标签的信息,然后将其动态的添加到布局中,并且我们能够得到我们选择容器的信息,并将选中的标签重新返回至服务器。

因此,我们必须计算出每个标签(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));

    }

onLayout()方法

计算好长度和宽度之后,我们就可以进行布局了。

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) {
        }
    });

}

效果

最后,让我们来看看实现效果




技术分享



结束语

这个自定义控件我感觉还是挺实用的,所以我会抽出时间将它整理,便于他人调用,项目的地址是标签云控件,欢迎大家指正。

参考资料

Johnny Huang的博客

标签流控件的实现

标签:

原文地址:http://my.oschina.net/weiCloudS/blog/382689

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!