概念
google开源的一套解决复查布局的控件,可以替换Anddroid里的LinearLayout+RelativeLayout,
最重要差异在于 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>
效果:
代码实现
效果
属性讲解
直接在布局加入,如下:
<?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的属性)的效果
跟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的值 |
属性定义了在分配多余空间之前,子元素 占据的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:主轴为垂直方向,起点在下沿
水平反向与垂直反向
flexWrap
换行属性。我们把上面的demo加上该属性试试,首先我们先把水平方向填满
然后分别加上flexWrap属性,值为wrap,wrap-reverse
发现两个都换行了,而且reverse的时候,是最后添加的text3在最上面
justifyContent
可以看到前三个属性类似gravity,而后两个类似于LinearLayout里的weight属性
- alignContent
属性定义项目在副轴轴上如何对齐
这里解释下什么是主/副轴,看图:
这个属性什么情况下起作用呢?
当主轴是水平方向时,只有存在多行的情况下,这个属性才起左右,如图:
添加了没有任何效果,咱们现在换成多行试试:
alignItem
单行的情况下也生效
子控件属性
layout_order
-
layout_flexBasisPercent
只有在父布局为MeasureSpec.EXACTLY(
wrap_parent -> MeasureSpec.AT_MOST
match_parent -> MeasureSpec.EXACTLY
具体值 -> MeasureSpec.EXACTLY)时生效,设置三个模式看下效果
wrap_parent(没有效果) match_parent(有效果) 指定值(有效果)
-
layout_wrapBefore
对比下设置的效果
项目应用
看下是否能替换咱们APP里的布局,找了好几个页面,发现只有个人中心→设置→
更多→关于 这个页面稍微简单点,而且里面是LinearLayout+RelativeLayout的组合
效果图及布局文件结构如下:
尝试着用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/'
}