前言
FlexboxLayout 已经出生两年多了,也使用过了多次,但当再次使用的时候,总会忘记各属性的效果是怎样的,人老了果然是健忘,所以为了加深理解和以后查阅,特写此文。
官网地址:https://github.com/google/flexbox-layout
FlexboxLayout 是谷歌开源的一个布局控件,借鉴的是 CSS 的 Flexible Box 布局,跟 Android 的 LinearLayout 比较像,需要设置水平或垂直方向,但 FlexboxLayout 更强大,下面就让我们去一探究竟。
使用
导入 build.gradle
1 | dependencies { |
先来个最原始的,所有属性都采用默认
布局
1 | <?xml version="1.0" encoding="utf-8"?> |
效果
这效果没啥可说的,下面开始对属性一一讲解
FlexboxLayout 支持的属性
flexDirection
决定主轴的方向,即 FlexboxLayout 子类的排列方向,有以下四种取值:
- row(默认):水平方向,起点在左边
- row_reverse:水平方向,起点在右边
- column:垂直方向,起点在顶部
- column:垂直方向,起点在底部
下面是效果,为了更方便的看效果,这里要先设置一个 alignItems
属性
1 | app:alignItems="flex_start" |
等会再解释这个属性,现在来看 flexDirection 属性各种取值的效果
flexWrap
控制 flex 容器是单行还是多行,并决定副轴(垂直主轴的方向)的起点位置,有以下三种取值:
- nowrap(默认):单行(不换行)
- wrap :正常换行
- wrap_reverse:反方向换行
这里为了更方便的看效果,又得多设置一个属性 alignContent
1 | app:alignContent="flex_start" |
同样,等会再解释这个属性,现在我的布局这样的
1 | <?xml version="1.0" encoding="utf-8"?> |
效果
justifyContent
控制主轴方向的对齐方式,有以下五种取值:
- flex_start(默认):左对齐
- flex_end:右对齐
- center:居中
- space_between:两端对齐,除两端外,多余空间平分中间间隔
- space_around:两端对齐,多余空间平分到子控件两侧,相当于给子控件设置了左右 margin
效果(默认效果这里就不贴了)
alignItems
控制副轴方向的对齐方式,如果是多行的情况,效果会受到 alignContent
属性的影响, 有以下五种取值:
- stretch(默认):如果固定高度或者
match_parent
时,子控件就会充满 FlexboxLayout 的高度,这也是为啥我们在看flexDirection
属性效果时,需要设置此属性的原因。 - flex_start:起点方向对齐,因为这个起点会受
flexDirection
属性影响,所以不能纯粹说顶部对齐 - flex_end:终点方向对齐
- center:居中
- baseline:以每行第一个子控件的文字基线对齐
效果
alignContent
控制多行时,容器的对齐方式,单行时设置无效,和 alignItems
同时使用时,效果会相互影响,对于 alignItems
属性的部分取值,会起到覆盖作用,有以下六种取值:
- stretch(默认):在
alignItems
设置为stretch
时子控件充满单行高度;在alignItems
设置为其他值时,子控件保留自身高度,但多行高度还是会充满 FlexboxLayout 的高度,这也是为啥我们在看flexWrap
效果时需要设置此属性的原因 - flex_start:起点方向对齐
- flex_end:终点方向对齐
- center:居中
- space_between:两端(副轴)对齐,除两端外,多余空间平分中间间隔
- space_around:两端(副轴)对齐,多余空间平分到单行上下两侧,相当于给单行设置了上下 margin
效果( alignItems
取默认值)
showDividerHorizontal
控制是否显示水平方向的分割线,值为(none | beginning | middle | end)一个或者多个
dividerDrawableHorizontal
设置水平方向的分割线
showDividerVertical
控制是否显示垂直方向的分割线,值为(none | beginning | middle | end)一个或者多个
dividerDrawableVertical
设置垂直方向的分割线
showDivider
控制是否显示分割线(包括水平和垂直方向),值为(none | beginning | middle | end)一个或者多个
dividerDrawable
设置分割线(包括水平和垂直方向),注意,如果跟 justifyContent="space_around"
或者 alignContent="space_between"
等属性值一起使用时,会看到意想不到的空间,所以如果不是想要的效果避免跟这些属性值同时使用
下面看个分割线的例子:
分割线 res/drawable/divider.xml
1 | <?xml version="1.0" encoding="utf-8"?> |
布局
1 | <?xml version="1.0" encoding="utf-8"?> |
效果
FlexboxLayout 子控件支持的属性
layout_order(integer)
默认情况下子控件的排列顺序是按照布局中的顺序依次出现,或者代码中的子控件的添加顺序排列,但可以通过设置此属性控制排列顺序,取值从小到大依次排列,默认为 1
举例将第二个元素的此属性设置为 0
1 | <?xml version="1.0" encoding="utf-8"?> |
效果
layout_flexGrow(float)
子控件的放大比例,决定如何分配剩余空间(如果有剩余空间的话),如果有多个子控件设置了此属性,则将剩余空间按比例分配给子控件,此属性类似 LinearLayout
的 layout_weight
属性,如果没有设置,默认值为 0
layout_flexShrink(float)
子控件的缩小比例,当空间不足时,决定是否缩小子控件(仅在不换行的时候有效),如果设置为 0
,则不对子控件进行缩小;如果设置为正数,则按比例缩小;如果不设置,默认值为 1
layout_alignSelf
给子控件设置在副轴方向上的对齐方式,和 alignItems
一样,区别在于 alignItems
作用于所有子控件,而此属性只控制单个子控件,有以下六种取值:
- auto(默认),表示继承
alignItem
属性值 - flex_start:起点方向对齐,
- flex_end:终点方向对齐
- center:居中
- baseline:以文字基线对齐
- stretch:充满
为了查看效果,FlexboxLayout 设置如下
1 | app:alignContent="stretch" |
效果
layout_flexBasisPercent(fraction)
子控件的宽或者高在 FlexboxLayout 中的百分比,设置的是主轴方向的,比如主轴是水平方向,则控制子控件的宽度在容器内的百分比。设置此值后将覆盖 layout_width
(或 layout_height
) 的值,此属性只有在 FlexboxLayout 的主轴方向的长度是固定(也就是 MeasureSpec mode 是 MeasureSpec.EXACTLY)时有效,默认值为 -1
layout_minWidth / layout_minHeight(dimension)
设置最小宽或者最小高,在 layout_flexShrink
作用时,子控件不会小于此最小值
layout_maxWidth / layout_maxHeight(dimension)
设置最大宽或者最大高,在 layout_flexGrow
作用时,子控件不会大于此最大值
layout_wrapBefore(boolean)
强制换行,flexWrap
属性设置为可换行时生效,默认为 false
,当设置为true
,则该子控件将成为新的一行的第一个元素
总结
果然亲自体验一遍印象比较深刻,总的说来这控件还是很强大的,特别是要实现热门标签这种需求简直再合适不过。google 还提供了 FlexboxLayoutManager
用于 RecyclerView
中,可以实现瀑布流的效果,在官网里头有demo,用起来很简单,基本上刚介绍的属性大部分都可以设置,区别在于增加了回收功能,官网 demo 地址:
https://github.com/google/flexbox-layout/tree/master/demo-cat-gallery
谨以此记录