超简单android自定义控件流式布局SimpleFlowLayout

技术的进步,总是由需求推动的 ——安卓君

1、前言

流式布局是app开发中必不可少的布局方式,例如照片墙,筛选标签等等。基本上每个app里面都可以看到这样的布局,但是android API中并没有提供实现流式布局方式的控件,因此自己实现一个流式布局的控件就非常有必要了。本文分享笔者实现FlowLayout思考过程,希望能够抛转引玉,为大家提供一个新的思路,文章末尾有代码链接。

2、效果

下面是效果图:

SimpleFlowLayout示例图

3、分析

实现自定义控件肯定要从View的绘制原理开始思考,关于View的绘制原理这里就不做介绍了。首先可以确定的是我们要实现的是一个ViewGroup,多个标签(子控件(View)) 被放置到ViewGroup中。所以要实现的有:

  • 1.测量父控件(ViewGroup)的大小
  • 2.放置子控件(View)

体现在代码中就是实现父控件的两个方法:

  • 1.onMeasure()
  • 2.onLayout()

3.1、计算父控件的宽高

3.1.1 计算父控件宽度

流式布局宽度一般都是指定的,match_parent 或者具体数值。测量模式为MeasureSpec.EXACTLY,可以通过MeasureSpec.getSize(widthMeasureSpec);方法获取。如果不是指定宽度,就无法换行摆放子控件,流式布局也就不存在了。

3.1.2 计算父控件的高度

结合效果图看,父控件的高度由子控件行数决定的,本文假设每个子控件高度一致,行间距一致,间隔一致。

父控件高度 = paddingTop + paddingBottom + 行高*行数 + 行间距*(行数 - 1)
计算高度

可以看到计算高度的关键是\color{red}{行数}\,所以剩下的问题就是如何计算行数。

如何计算行数?

计算行数的关键在于知道什么时候换行,我们先看看效果图每一行子控件实际占据的宽度


计算宽度

在FlowLayout中,一行子控件实际占据宽度为

行宽度 = 子控件宽度 + 间隔 ... (间隔数比子控件少一个)

所以我们可以很容易得出这样一个换行条件

paddingLeft + 行宽度 +  下一个子控件的宽度 + paddingRight > 父控件宽度

我们可以通过for循环遍历子控件集合计算出总行数,当我们得出行数时,就可以计算出父控件的高度,测量宽高的工作就完成了。

3.2 放置子控件

放置子控件,最终调用

layout(int l, int t, int r, int b)

所以只要得到每个子控件的位置信息就可以最终展现出流式布局,很多人在实现FlowLayout时,会在这里重新测量再计算子控件的位置,我觉得比较繁琐,而且重复的测量也耗费资源。我想到,在onMeasure()方法中,需要遍历子控件计算宽高,那么为什么不在遍历的时候,计算出每个子控件的位置,再通过setTag()方法把位置信息赋值给子控件呢?那样的话在执行onLayout()方法,放置子控件的时候,就可以通过遍历子控件,getTag() 得到每个子控件的位置信息,就可以实现所有子控件的放置了。

如何计算每个子控件的位置?

计算子控件位置

如上图所示,只要计算出子控件的宽高,我们很容易就能得出left,top,bottom,right值。

4.实现单选和多选

如何实现子控件的单选功能?

可以借鉴RadioGroup实现原理,也可以换一种思路,直接继承RadioGroup就可以实现单选的功能,添加RadioButton作为子控件,相当于把RadioGroup改造成具有流式布局功能的控件。

如何实现子控件的多选功能?

如果添加的子控件都是CheckBox,就可以实现多选的功能。

5.总结

FlowLayout算不上非常复杂的控件,原理也很简单,一个是计算父容器的宽高,一个是获取子控件的位置。本文从笔者实际业务出发,行间距,间隔都是在自定义属性中设置的固定值,实现起来也简单。自认为本文特别之处在于,提供新的思路,让流式布局实现起来更简单优雅

在测量子控件时,计算每个控件的位置,并设置到子控件

本文主要分享思考过程、实现方法,不能说多完美,希望能带给大家一点启发。作者欢迎评论,探讨!
源码地址:https://github.com/f1mert/SimpleFlowLayout 欢迎点击!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容