Android上的Flexbox布局
splash
8年前
<h3>简介</h3> <p>最近Google开源了一个叫 flex-box 的库,它的思路是参照的 <strong>CSS的Flex布局</strong> 设计的,所以属性基本都是和CSS上的Flex布局保持一致,但因为是两个不同的平台,所以减少了几个不适用于Android的属性,新增了几个属性,具体我们下面会说到。</p> <h3>关于CSS的Flex布局</h3> <p>在了解Google开源的 <strong>flex-box</strong> ,我觉得有必要先了解下 <strong>CSS的Flex布局</strong> ,这有助于我们理解那些属性定义。关于这方面的知识,可以阅读这篇博客。下面我们只是简要的了解下,具体属性我们放到讲解Google的 <strong>flex-box</strong> 中去说明。</p> <pre> //这段文字说明,来源于上面说到的博客 采用Flex布局的元素,称为Flex容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称"项目"。 容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。 项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。</pre> <p style="text-align: center;"><img src="https://simg.open-open.com/show/8b402883445b842ca38727fc09f60d00.png"></p> <p style="text-align: center;">img</p> <h3>关于Google的flexbox-layout</h3> <p>注意:以下文中用到的flexbox-layout指的是Google开源的库,Flex指的是CSS中的Flex布局。</p> <p>首先我们需要知道的是,flexbox-layout的基本概念和Flex是一样的,最外面的这层布局称为 <strong>容器</strong> ,在flexbox-layout指的是 com.google.android.flexbox.FlexboxLayout ,里面的子元素称为 <strong>项目</strong> 。容器默认存在两条轴,其中水平(这里是就上面的概念图而言,因为主轴的方向是可以指定的)的这条轴称为 <strong>主轴</strong> (个人理解,可以存在多条,具体原因后面讲),垂直的这条称为 <strong>交叉轴</strong> 。其他属性比如 start , end 等等也是一样的,具体可以看上面的基本概念图。</p> <p>下面我们着重讲下flexbox-layout支持的属性,因为它既支持容器属性,也支持项目属性,所以我们分成两个篇幅来说明。</p> <p>注意:以下属性设置的具体效果请参照说明文档和Demo, <a href="/misc/goto?guid=4959746529077926276" rel="nofollow,noindex">github地址</a></p> <p>容器属性</p> <ul> <li> <p>flexDirection</p> <p>这个属性用于确定 <strong>主轴方向</strong> ,可选的值有:</p> <ol> <li>row 水平方向,起点在左边。默认值</li> <li>row_revers 水平方向,起点在右边。</li> <li>column 垂直方向,起点在上边。</li> <li>column_reverse 垂直方向,起点在下边。</li> </ol> </li> </ul> <p> </p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/0ac377493a33869f2829c4b1d3d70100.png"></p> <p style="text-align: center;"> </p> <ul> <li>flexWrap</li> </ul> <p>这个属性控制容器是单行还是自动换行,以及主轴的方向,可选的值有:</p> <p>关于 wrap 和 wrap-reverse 的区别:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/6215cf568af888a6442517b68a2825d8.jpg"></p> <p> </p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/4a8a486060e81a05895277c987af5c96.jpg"></p> <ol> <li>nowrap 单行。默认值</li> <li>wrap 自动换行,第一行在上方</li> <li>wrap-reverse 自动换行,第一行在下方</li> </ol> <p>justifyContent</p> <p>这个属性控制项目在主轴上的对齐方式,可选的值有:</p> <p>注意:具体的对齐方式与主轴的方向有关,下面的说明是基于默认值</p> <p>关于 space_between 和 space_around 的样式如下:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/04f0d371b9d08744bdb04906af761823.png"></p> <p> </p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/3fb46f663165c571e87e12192445b592.png"></p> <ol> <li>flex_start 左对齐,默认值</li> <li>flex_end 右对齐</li> <li>center 居中对齐</li> <li>space_between 两端对齐,项目之间的间隔相等</li> <li>space_around 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍</li> </ol> <ul> <li> <h3>alignItems</h3> </li> </ul> <p>这个属性定义项目在交叉轴上的对齐方式,可选的值有:</p> <p>注意:具体的对齐方式与主轴的方向有关</p> <p>关于 stretch 和 baseline 的样式如下:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/22ee1d62ff60146cadd3b8a97026eefe.png" alt="Android上的Flexbox布局" width="415" height="604"></p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/0b011da4e89eb64b4f14cdec5eb9a943.png"></p> <ol> <li>stretch 占满整个容器高度,默认值</li> <li>flex_start 交叉轴的起点对齐</li> <li>flex_end 交叉轴的终点对齐</li> <li>center 居中对齐</li> <li>baseline 项目的第一行文字的基线对齐</li> </ol> <ul> <li> <p>alignContent</p> <p>这个属性控制容器的多条主轴的对齐方式,这也是我们前面提到的 <strong> 主轴可以有多条,当 flexWrap:wrap|wrapreverse </strong> 。可选的值有:</p> <p>注意:只有一条主轴,该属性不起作用</p> <p>这里需要注意区别下和 alignItems 的区别, alignContent 是多条主轴基于交叉轴的对齐方式,而后者是项目基于交叉轴的对齐方式,一个是轴,一个是项目。</p> <ol> <li>stretch 占满整个交叉轴,默认值</li> <li>flex_start 与交叉轴的起点对齐</li> <li>flex_end 与交叉轴的终点对齐</li> <li>center 与交叉轴的中心对齐</li> <li>space_between 与交叉轴两端对齐,轴线之间的间隔平均分布</li> <li>space_around 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍</li> </ol> </li> <li> <p>showDividerHorizontal</p> </li> <li> <p>dividerDrawableHorizontal</p> </li> <li> <p>showDividerVertical</p> </li> <li> <p>dividerDrawableVertical</p> </li> <li> <p>showDivider</p> </li> <li> <p>dividerDrawable</p> <p>这几个属性都是跟分隔符有关,具体用法可以看文档。</p> </li> </ul> <p>项目属性</p> <ul> <li> <p>layout_order(integer)</p> <p>这个属性可以改变项目的排列顺序,默认值为 1 。</p> </li> <li> <p>layout_flexGrow(float)</p> <p>这个属性定义项目基于当前行的放大比例,默认值为 0 。这个属性类似 LinearLayout 中的 layout_weight 属性,如果当前行只有一个项目的 layout_flexGrow 为正值,则该项目将占满当前行剩余的空间,下面的效果是三个相同大小的项目,其中一个 layout_flexGrow 为正值的效果:</p> </li> </ul> <p style="text-align: center;"><img src="https://simg.open-open.com/show/fb56557f80203ac0be8b6bd1adb1560e.png"></p> <p style="text-align: center;"> </p> <p>如果存在多个 layout_flexGrow 为正值的情况,则这几个项目则会按设置的值为比例占用当前行剩余的空间,下面的效果是三个相同大小的项目,其中两个项目设置 layout_flexGrow:1 的效果:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/017447c21a98793031cfa2cb97d940d5.png"></p> <ul> <li> <p>layout_flexShrink(float)</p> <p>这个属性定义了项目的缩小比例,默认为 1 ,即如果当前行空间不足,该项目缩小的方式。</p> <p>如果所有项目的 layout_flexShrink 属性都为1,当空间不足时,都将等比例缩小。如果一个项目的 layout_flexShrink 属性为0,其他项目都为1,则空间不足时,前者不缩小。</p> <p>个人理解,注意:要设置 flexWrap:nowrap 为单行</p> </li> <li> <p>layout_alignSelf</p> <p>该属性允许单个项目与其他项目不一样的基于交叉轴的对齐方式。默认值为 auto ,即按照容器的 alignItems 属性,设置其他值,则会覆盖容器的值,可选的值:</p> <ol> <li>auto 默认值</li> <li>flex_start</li> <li>flex_end</li> <li>center</li> <li>baseline</li> <li>stretch</li> </ol> </li> <li> <p>layout_flexBasisPercent(fraction)</p> <p>这个属性设置项目长度相对于容器的百分比,如果设置了这个值,则从 layout_width 或 layout_height 指定的长度会被覆盖,需要注意的是,这个属性只在容器长度确定的情况下有效,即 MeasureSpec.EXACTLY 。默认值为 -1 ,表示不设置。</p> </li> <li> <p>layout_minWidth/ <strong>layout_minHeight</strong> (dimension)</p> </li> <li> <p>layout_maxWidth/ <strong>layout_maxHeight</strong> (dimension)</p> <p>这些属性设置对项目的最大最小限制</p> </li> <li> <p>layout_wrapBefore(boolean)</p> <p>这个属性默认值为 false ,如果设置为 true ,则该项目将强制成为当前行的第一个项目,会忽略 flex_wrap:nowrap 设置。</p> </li> </ul> <h3>应用实例</h3> <ol> <li> <p>底部按钮</p> </li> </ol> <p style="text-align: center;"><img src="https://simg.open-open.com/show/2a68c5f68f6bd76548828f9b7a1008e7.png" style="font-size:13px; line-height:1.6"></p> <p> </p> <p>2.流式布局</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/a62a3255dca22416fbf015e90c5dd8c4.png"></p> <p> </p> <p> </p> <p>来自:https://juejin.im/post/58dde21461ff4b006b0b0cc4</p> <p> </p>