本文是官方文档的翻译
FlexboxLayout 是一个库项目,能在Android上实现类似CSS Flexible Box Layout Module 的能力。
添加以下依赖到你的build.gradle
文件中:
dependencies {
implementation 'com.google.android:flexbox:1.0.0'
}
在布局中有两种方式使用FlexBox
第一种是像LinearLayout
和 RelativeLayout
那样,FlexboxLayout
都是继承了 ViewGroup
。
你可以指定属性在一个布局XML,如:
<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="match_parent"
app:flexWrap="wrap"
app:alignItems="stretch"
app:alignContent="stretch" >
<TextView
android:id="@+id/textview1"
android:layout_width="120dp"
android:layout_height="80dp"
app:layout_flexBasisPercent="50%"
/>
<TextView
android:id="@+id/textview2"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_alignSelf="center"
/>
<TextView
android:id="@+id/textview3"
android:layout_width="160dp"
android:layout_height="80dp"
app:layout_alignSelf="flex_end"
/>
com.google.android.flexbox.FlexboxLayout>
或者通过代码像:
FlexboxLayout flexboxLayout = (FlexboxLayout) findViewById(R.id.flexbox_layout);
flexboxLayout.setFlexDirection(FlexDirection.ROW);
View view = flexboxLayout.getChildAt(0);
FlexboxLayout.LayoutParams lp = (FlexboxLayout.LayoutParams) view.getLayoutParams();
lp.order = -1;
lp.flexGrow = 2;
view.setLayoutParams(lp);
第二种方式是 FlexboxLayoutManager
可以使用在 RecyclerView
的内部.
RecyclerView recyclerView = (RecyclerView) context.findViewById(R.id.recyclerview);
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(context);
layoutManager.setFlexDirection(FlexDirection.COLUMN);
layoutManager.setJustifyContent(JustifyContent.FLEX_END);
recyclerView.setLayoutManager(layoutManager);
或者通过孩子的属性的 FlexboxLayoutManager
你可以这样做:
mImageView.setImageDrawable(drawable);
ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
FlexboxLayoutManager.LayoutParams flexboxLp = (FlexboxLayoutManager.LayoutParams) lp;
flexboxLp.setFlexGrow(1.0f);
flexboxLp.setAlignSelf(AlignSelf.FLEX_END);
}
使用FlexboxLayoutManager
的优点是它可以回收从屏幕上消失的views,为了重用那些出现在用户滚动条上的视图而不是每次都inflate每个单独的view,
这样做可以消耗小得多的内存特别是当Flexbox容器包含了item的总数是很大的时候。
由于RecyclerView
的一些特征,有些FlexBox的属性不可用或者没有实现在FlexboxLayoutManager
。
下面是两个实现之间的属性/特性比较的快速概述
Attribute / Feature | FlexboxLayout | FlexboxLayoutManager (RecyclerView) |
---|---|---|
flexDirection | ||
flexWrap | (except wrap_reverse ) |
|
justifyContent | ||
alignItems | ||
alignContent | - | |
layout_order | - | |
layout_flexGrow | ||
layout_flexShrink | ||
layout_alignSelf | ||
layout_flexBasisPercent | ||
layout_(min/max)Width | ||
layout_(min/max)Height | ||
layout_wrapBefore | ||
Divider | ||
View recycling | - | |
Scrolling | *1 |
*1 部分可能用ScrollView
来包装,但是它不太可能用作与一个大集合布局内部的视图,因为它不考虑到视图的回收
flexDirection
flexWrap
justifyContent
alignItems
alignContent
showDividerHorizontal (one or more of none | beginning | middle | end
)
dividerDrawableHorizontal (reference to a drawable)
*在flex线之间放置水平分隔物 (or flex items when flexDirection
is set to column
or column_rebase
).
showDividerVertical (one or more of none | beginning | middle | end
)
dividerDrawableVertical (reference to a drawable)
column
or column_rebase
).showDivider (one or more of none | beginning | middle | end
)
dividerDrawable (reference to a drawable)
justifyContent="space_around"
or alignContent="space_between"
… etc) 将 同时放置水平和垂直分割线的例子。
res/drawable/divider.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size
android:width="8dp"
android:height="12dp" />
<solid android:color="#44A444" />
shape>
res/layout/content_main.xml
<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="match_parent"
app:alignContent="flex_start"
app:alignItems="flex_start"
app:flexWrap="wrap"
app:showDivider="beginning|middle"
app:dividerDrawable="@drawable/divider" >
<TextView
style="@style/FlexItem"
android:layout_width="220dp"
android:layout_height="80dp"
android:text="1" />
<TextView
style="@style/FlexItem"
android:layout_width="120dp"
android:layout_height="80dp"
android:text="2" />
<TextView
style="@style/FlexItem"
android:layout_width="160dp"
android:layout_height="80dp"
android:text="3" />
<TextView
style="@style/FlexItem"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="4" />
<TextView
style="@style/FlexItem"
android:layout_width="100dp"
android:layout_height="80dp"
android:text="5" />
layout_order (integer)
layout_flexGrow (float)
layout_flexGrow
的值,在flex行中这个item将占据剩余的部分。如果相同 layout_flexGrow
正数的值,剩下的自由的空间分配根据他们声明的layout_flexGrow
值得比例。(类似 LinearLayout
的layout_weight
属性)如果不指定,这个值默认设置为0
layout_flexShrink (float)
1
layout_alignSelf
alignItems
决定,但是如果这个属性设置了 auto
,交叉轴的对齐将会被子view重写,可能的值:layout_flexBasisPercent (fraction)
layout_width
(或者 layout_height
)指定的长度会被重写通过这个分数计算的到的值。 MeasureSpec.EXACTLY
)。默认值是-1
,以为着不设置。layout_minWidth / layout_minHeight (dimension)
flexDirection
属性是指哪个属性将大小限制强加于主轴),不管layout_flexShrink
属性layout_maxWidth / layout_maxHeight (dimension)
flexDirection
属性是指哪个属性将大小限制强加于主轴),不管layout_flexGrow
属性layout_wrapBefore (boolean)
这个库尝试尽可能跟原
Flexible Box specification 功能相同,
但是由于某些原因,比如指定属性的方式在这两者之间是不一样的
CSS和Android XML,与原始规范有一些已知的区别
(1) 没有与 flex-flow
等效的属性
* 因为flex-flow
是设置flex-direction
和flex-wrap
属性的缩写,
从单个属性中指定两个属性在Android中是不实用的。
(2) 没有flex 等效属性
* 同样的,flex
是设置flex-grow
、flex-shrink
和flex-basis
的缩写,
从单个属性中指定这些属性是不实际的。
(3)layout_flexBasisPercent
被引入,而不是
flexBasis
* 本库中的layout_flexBasisPercent
和CSS中的flex-basis
属性都被用于
确定单个flex项目的初始长度。flex-basis
属性接受宽度
诸如1em
、10px
、content
等值,以及诸如此类的百分比值
“10%”和“30%”。layout_flexBasisPercent
只接受百分比值。
但是,指定初始固定宽度值可以通过指定宽度(或高度)值来完成
layout_width(或layout_height,取决于flexDirection
)。同时,相同的
layout_width(或layout_height)中指定”wrap_content”来实现效果。
开发人员想要达到与 ‘content’相同的效果。因此,只有layout_flexBasisPercent
接受百分比值,这不能通过ayout_width(或layout_height)来简单完成
(4) layout_wrapBefore
已经介绍.
* 在CSS灵活的Box模块规范中不存在等价的属性,
但正如上面所解释的,Android开发者将会受益于拥有这个属性
当包装发生时,更多的控制。