详解FlexboxLayout的使用

时间:2021-11-20 17:02:45

详解FlexboxLayout的使用

概念

  google开源的一套解决复查布局的控件,可以替换Anddroid里的LinearLayout+RelativeLayout,

  最重要差异在于 FlexboxLayout 具有 “换行” 的特性,可便捷的写出流式布局。

场景

详解FlexboxLayout的使用


使用

  安装配置

  bulid.gradle文件(module)

 dependencies {
compile 'com.google.android:flexbox:0.2.6'
}

 

实现

xml实现

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexDirection="row"
app:justifyContent="space_around"
app:flexWrap="wrap">

<TextView
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="吃货"
android:layout_marginBottom="10dp"/>
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="逗比" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="创业者" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="上班这点事" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="影视天堂" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="大学生活" />
<TextView
android:padding="6dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="单身狗" />
<TextView
android:padding="6dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="运动和健身" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="网购达人" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="旅游" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="程序员" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="追星族" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="短篇小说" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="美食" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="教育" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="教育" />
<TextView
android:layout_marginBottom="10dp"
android:padding="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_text"
android:text="汪星人" />

</com.google.android.flexbox.FlexboxLayout>


详解FlexboxLayout的使用

效果:

详解FlexboxLayout的使用

代码实现

详解FlexboxLayout的使用

效果

详解FlexboxLayout的使用

属性讲解

  直接在布局加入,如下:

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.flexbox.FlexboxLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
<TextView
  android:text="textview1"
  android:id="@+id/textview1"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
   <TextView
  android:text="textview2"
  android:id="@+id/textview2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
<TextView
  android:text="textview3"
  android:id="@+id/textview3"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
 />
</com.google.android.flexbox.FlexboxLayout>

  咱们先看下没有添加额外属性(FlexboxLayout的属性)的效果

  详解FlexboxLayout的使用

  跟LinearLayout一样,默认是水平方向的

  代码动态加入,如下:

FlexboxLayout flexboxLayout = (FlexboxLayout) findViewById(R.id.flexbox_layout);
flexboxLayout.setFlexDirection(FlexboxLayout.FLEX_DIRECTION_COLUMN); 

View view = flexboxLayout.getChildAt(0);
FlexboxLayout.LayoutParams lp = (FlexboxLayout.LayoutParams) view.getLayoutParams();
lp.order = -1;
lp.flexGrow = 2;
view.setLayoutParams(lp);

  支持的属性

属性 说明 备注

flexDirection

 

row 默认值,主轴为水平方向,起点在左端

决定主轴的方向,

类似 LinearLayout 的 vertical 和 horizontal


row-reverse 主轴为水平方向,起点在右端
column 主轴为垂直方向,起点在上沿
column-reverse 主轴为垂直方向,起点在下沿

flexWrap



nowrap


不换行

默认情况下 Flex 跟 LinearLayout 一样,

都是不带换行排列的,但是flexWrap

属性可以支持换行排列

wrap 按正常方向换行
wrap-reverse 按反方向换行

justifyContent


flex-start


默认值,左对齐

 属性定义了项目

在主轴上的对齐方式

这三个值类似于gravity

flex-end: 右对齐
center 居中
space-between 两端对齐,项目之间的间隔都相等  属性定义了项目 

在主轴上的对齐方式

 这两个类似于LinearLayout里的weight属性

space-around

每个项目两侧的间隔相等。所以,

项目之间的间隔比项目与边框的间隔大一倍

alignContent



flex-start

交叉轴的起点对齐

定义了多根轴线的对齐方式。

如果项目只有一根轴线,该属性不起作用,

这个属性需要下面会着重讲下,因为网上很多论坛都

是千篇一律的一笔带过,压根看不懂。




flex-end 交叉轴的终点对齐
center 交叉轴的中点对齐
baseline 项目的第一行文字的基线对齐
stretch

默认值,如果项目未设置高度或设为auto,

将占满整个容器的高度

alignItems


flex-start 交叉轴的起点对齐

定义项目在副轴轴上如何对齐,

 该属性与alignContent区别在于,alignContent只对多

行起作用,而alignitem对每一行都起作用,下面看效果

flex-end 交叉轴的终点对齐
center 交叉轴的中点对齐
baseline 项目的第一行文字的基线对齐
stretch

默认值,如果项目未设置高度或设为auto,

将占满整个容器的高度

layout_order-子控件

    这个属性主要用于子控件的,

可以控制排列的顺序,负值在前,

 正值灾后,按照从小到大的顺序依次排列

layout_flexGrow-子控件

 默认为0 跟LinearLayout的weight类似  定义项目的放大比例
layout_flexShrink-子控件 默认为1   定义了项目的缩小比例
layout_alignSelf-子控件     与align-item相同
layout_flexBasisPercent-子控件 百分数

只有在父布局为

MeasureSpec的值

 MeasureSpec.EXACTLY

属性定义了在分配多余空间之前,子元素

占据的main size主轴空间,浏览器根据

这个属性,计算主轴是否有多余空间。

它的默认值为auto,即子元素的本来大小(不知讲的啥。。。还是看效果吧)

layout_minWidth / layout_minHeight     item 的最小宽度/高度
layout_maxWidth / layout_maxHeight     item 的最大宽度/高度
layout_wrapBefore    

item 是否在 flex line 的第一个,默认为 false,

在父布局app:flexWrap="nowrap"时不起作用

 

  • flexDirection

    • row-reverse:主轴为水平方向,起点在右端。

    • column-reverse:主轴为垂直方向,起点在下沿

      水平反向与垂直反向

         详解FlexboxLayout的使用

         详解FlexboxLayout的使用

  • flexWrap

          换行属性。我们把上面的demo加上该属性试试,首先我们先把水平方向填满

          详解FlexboxLayout的使用

        然后分别加上flexWrap属性,值为wrap,wrap-reverse

        详解FlexboxLayout的使用详解FlexboxLayout的使用

      发现两个都换行了,而且reverse的时候,是最后添加的text3在最上面

  • justifyContent

        详解FlexboxLayout的使用详解FlexboxLayout的使用
       详解FlexboxLayout的使用详解FlexboxLayout的使用 

       详解FlexboxLayout的使用
       可以看到前三个属性类似gravity,而后两个类似于LinearLayout里的weight属性

  • alignContent  

         属性定义项目在副轴轴上如何对齐

         这里解释下什么是主/副轴,看图:

         详解FlexboxLayout的使用
         这个属性什么情况下起作用呢?
         当主轴是水平方向时,只有存在多行的情况下,这个属性才起左右,如图:
         详解FlexboxLayout的使用 
         添加了没有任何效果,咱们现在换成多行试试:
         详解FlexboxLayout的使用详解FlexboxLayout的使用

alignItem

单行的情况下也生效

详解FlexboxLayout的使用

子控件属性

  • layout_order

        看下添加该属性前后的效果对比图        详解FlexboxLayout的使用详解FlexboxLayout的使用
  • layout_flexBasisPercent

    只有在父布局为MeasureSpec.EXACTLY(
    wrap_parent -> MeasureSpec.AT_MOST
    match_parent -> MeasureSpec.EXACTLY
    具体值 -> MeasureSpec.EXACTLY)
    时生效,设置三个模式看下效果
    wrap_parent(没有效果)                                                                     match_parent(有效果)                                                     指定值(有效果)
    详解FlexboxLayout的使用详解FlexboxLayout的使用详解FlexboxLayout的使用
  • layout_wrapBefore

    对比下设置的效果详解FlexboxLayout的使用详解FlexboxLayout的使用 

          

项目应用

  看下是否能替换咱们APP里的布局,找了好几个页面,发现只有个人中心→设置→

  更多→关于 这个页面稍微简单点,而且里面是LinearLayout+RelativeLayout的组合

  效果图及布局文件结构如下:

  详解FlexboxLayout的使用详解FlexboxLayout的使用

  尝试着用FlexboxLayout替换这个布局,目的:去掉所有的RelativeLayout与LinearLayout,

  而且只有一个FlexboxLayout与所有的子控件。但是经过分析发现,没法到这个目标,因为

  这个页面里既有水平方向又有垂直方向的,而且底部还有一个利用RelativeLayout的

  layout_alignParentBottom="true"属性设置的,而FlexboxLayout也没有这个属性,虽然可以

  用FlexboxLayout的alignContent="flex_end"有这效果,但必须是水平的父布局,所以不能完全

  利用FlexboxLayout来替换该布局。突然想起里前面介绍里说过的一句话:

  “最重要差异在于 FlexboxLayout 具有 “换行” 的特性,可便捷的写出流式布局”。

结论

  适用场景

  • 自动换行
  • 流式布局

问题

  问题:

    Failed to resolve: com.google.android:flexbox:0.2.6

  解决:

  把最外层的build.gradle里配置的两个jcenter由默认的

 jcenter()改为
 jcenter{
url 'http://jcenter.bintray.com/'
}

Demo链接

参考

  https://github.com/google/flexbox-layout