文档章节

标签流控件的实现

fyales
 fyales
发布于 2015/03/04 20:46
字数 810
阅读 720
收藏 7

「深度学习福利」大神带你进阶工程师,立即查看>>>

前言

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

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

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

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

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

}

效果

最后,让我们来看看实现效果 <br /> <br /> pic <br /> <br />

结束语

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

参考资料

Johnny Huang的博客

fyales
粉丝 1
博文 18
码字总数 21081
作品 0
浦东
程序员
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
用vertx实现高吞吐量的站点计数器

工具:vertx,redis,mongodb,log4j 源代码地址:https://github.com/jianglibo/visitrank 先看架构图: 如果你不熟悉vertx,请先google一下。我这里将vertx当作一个容器,上面所有的圆圈要...

jianglibo
2014/04/03
4.3K
3
浅入浅出Android(003):使用TextView类构造文本控件

基础: TextView是无法供编辑的。 当我们新建一个项目MyTextView时候,默认的布局(/res/layout/activity_main.xml)中已经有了一个TextView: <TextView 运行效果如下: 修改其文本内容...

樂天
2014/03/22
706
1
SQLServer实现split分割字符串到列

网上已有人实现sqlserver的split函数可将字符串分割成行,但是我们习惯了split返回数组或者列表,因此这里对其做一些改动,最终实现也许不尽如意,但是也能解决一些问题。 先贴上某大牛写的s...

cwalet
2014/05/21
9.7K
0
NSSplitView 扩展--DMSplitView

DMSplitView 对标准的 OS X 的 NSSplitView 控件进行改造,可满足更复杂的要求: 子视图的大小和约束 分隔条位置 可收缩伸展的子视图 动画变换效果 可控制分隔条的粗细和样式 可保存和恢复分...

匿名
2013/01/24
371
0

没有更多内容

加载失败,请刷新页面

加载更多

红队之windows用户和组

目录 0x01 用户账户和组策略 0x02 Windows中的访问控制 0x03 安全标识符SID 0x04 用户账户控制(UAC) 用户帐户 用户帐户是对计算机用户身份的标识,本地用户帐户、密码存在本地计算机上,只...

黑白天安全团队
昨天
9
0
厉害了!百度智能云NIRO Pro智能机器人半年内连获三项产品设计大奖

短短半年内,百度智能云NIRO Pro智能机器人连获三项产品设计大奖,其中包括有“设计界奥斯卡”之称的德国红点奖,成功引领了全球助理机器人的工业设计和发展趋势风向标。红点奖评委这样评价,...

百度智能云
2019/12/04
0
0
StringBuider 在什么条件下、如何使用效率更高?

作者:后青春期的Keats cnblogs.com/keatsCoder/p/13212289.html 引言 都说 StringBuilder 在处理字符串拼接上效率要强于 String,但有时候我们的理解可能会存在一定的偏差。最近我在测试数据...

Object_Man
今天
6
0
发布更新|腾讯云 Serverless 产品动态 20200813

一、云函数 SCF + Ckafka 联合转储方案正式发布 发布时间: 2020-08-06 产品背景: SCF + Ckafka 联合转储方案可以帮忙用户节省使用与开发成本,用户可以将 Ckafka 消息转储同步转储至消息队...

腾讯云Serverless
37分钟前
5
0
如何正确强制执行Git推送? - How do I properly force a Git push?

问题: I've set up a remote non-bare "main" repo and cloned it to my computer. 我已经建立了一个远程的非裸露的“主”仓库,并将其克隆到我的计算机上。 I made some local changes, u......

javail
38分钟前
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部