美文网首页AndroidAndroid项目
超简单android自定义控件流式布局SimpleFlowLay

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

作者: 易说新语 | 来源:发表于2019-05-31 11:11 被阅读131次

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

    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 欢迎点击!

    相关文章

      网友评论

        本文标题:超简单android自定义控件流式布局SimpleFlowLay

        本文链接:https://www.haomeiwen.com/subject/tzpvtctx.html