今天分享一下彈性布局FlexboxLayout的使用總結,又是一篇個人有道云筆記轉移系列,早些年我們實作一個換行的標簽云、實作一個不規則的九宮格、實作一個不規整瀑布流等等這些“嘿嘿嘿”設計總是要思索半天,FlexboxLayout的出現面對這些問題將為你節省幾億個腦細胞不在話下,我第一次接觸這個布局方式還是從早前一個前端寫H5的小哥嘴里得到的,我順便舉一反三搜了一下發現我們Android上也有,還是google官方出品,看來知識都是相通的,好了,廢話不多說,直接淦!
GitHub
官方地址: https://github.com/google/flexbox-layout
接入依賴:
dependencies {
implementation 'com.google.android:flexbox:2.0.1'
}
值得注意的是從1.1.0開始,該庫直接對接AndroidX,如果想要使用1.1.0及以上版本盡快升級到AndroidX咯,
簡單使用方式
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>
From Code
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.setOrder(-1);
lp.setFlexGrow(2);
view.setLayoutParams(lp);
FlexboxLayoutManager (within RecyclerView)
// 針對所有item
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);
// 針對單個item
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);
}
相關屬性

下邊我直接介紹相關屬性使用方法
父布局屬性
以下五種是父布局中所使用的,也是最常用的,
flexDirection
flexDirection屬性是決定主軸的方向,好比LinearLayout的vertical(垂直) 和 horizontal(水平)方向,
- row:一般為默認值,主軸為水平方向,起點在左端,
- row-reverse: 主軸為水平方向,起點在右端,
- column:主軸為垂直方向,起點在上沿,
- column-reverse:主軸為垂直方向,起點在下沿,
flexWrap
flexWrap屬性是決定是否換行排列,默認情況下是不支持換行排列,
- nowrap:不換行,
- wrap: 正常方向換行,
- wrap-reverse: 反方向換行,
justifyContent
justifyContent指定了專案在主軸上的對齊方式,
- flex-start: 默認值為左對齊,
- flex-end: 右對齊,
- center: 居中,
- space-between: 兩端對齊,其間間距相等,
- space-around: 兩側間距相等,

alignltems
alignltems指定專案在副軸(交叉軸,和主軸垂直)上的對齊方式,
- flex-start: 交叉軸的起點對齊,(上)
- flex-end: 交叉軸的終點對齊,(下)
- center: 交叉軸的中點對齊,(中間線)
- baseline: 第一行文字的基線對齊,()
- stretch: 默認值是占滿整個容器的高度,在未設定高度或者為auto,

alignContent
alignContent指定多根軸線的對齊方式,如果只有一條軸,該屬性不起任何作用,
- flex-start: 與交叉軸的起點對齊,
- flex-end: 與交叉軸的終點對齊,
- center: 與交叉軸的中點對齊,
- space-between: 與交叉軸的兩端對齊,軸線之間的間隔分布均勻,
- space-around: 每根軸線兩側的間隔相等,
- stretch: 默認值為軸線占滿整個交叉軸,

分割線
水平分割線
采用showDividerHorizontal和dividerDrawableHorizontal屬性設定水平分割線
- showDividerHorizontal
控制顯示水平方向的分割線,值為none | beginning | middle | end其中的一個或者多個, - dividerDrawableHorizontal
設定Flex 軸線之間水平方向的分割線,
垂直分割線
采用showDividerVertical和dividerDrawableVertical屬性設定垂直分割線
- showDividerVertical
控制顯示垂直方向的分割線,值為none | beginning | middle | end其中的一個或者多個, - dividerDrawableVertical
設定子元素垂直方向的分割線,
水平垂直分割線
采用showDivider和dividerDrawable屬性同時設定水平垂直分割線
- showDivider
控制顯示水平和垂直方向的分割線,值為none | beginning | middle | end其中的一個或者多個, - dividerDrawable
設定水平和垂直方向的分割線,但是注意,如果同時和其他屬性使用,比如為Flex軸、子元素設定了justifyContent=“space_around”、alignContent=“space_between”等等,可能會看到意料不到的結果,因此應該避免和這些值同時使用,
子布局屬性
layout_order
這個屬性可以改變布局子視圖的順序,默認情況下,子元素的顯示和布局順序與布局XML中的順序相同,如果沒有指定,則將1設定為默認值( CSS 中默認值為 0) ,數值越小,排列越靠前,
layout_flexGrow
放大比例,這個屬性類似于 LinearLayout 中的 layout_weight 屬性,如果沒有指定,則將 0 設定為默認值,如果果同一 flex 行中的多個子 View 有正的 layout_flexGrow 值,那么剩余的空閑空間將根據它們宣告的 layout_flexGrow 值的比例分布,
<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="300dp"
android:layout_height="300dp"
android:background="@android:color/black">
<!--
flex-grow(放大比例,剩余空間怎么分配) : 權重
float FLEX_GROW_DEFAULT = 0f;
剩余寬度 = 300 - (0 + 0 + 0) = 300
tv1寬度 = 0 + 300 * (2 / 4) = 150
tv2寬度 = 0 + 300 * (1 / 4) = 75
tv3寬度 = 0 + 300 * (1 / 4) = 75
-->
<TextView
android:id="@+id/tv1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_purple"
android:gravity="center"
android:padding="5dp"
android:text="tv1"
android:textColor="@android:color/white"
app:layout_flexGrow="2" />
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#FFC107"
android:gravity="center"
android:padding="5dp"
android:text="tv2"
app:layout_flexGrow="1" />
<TextView
android:id="@+id/tv3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:gravity="center"
android:padding="5dp"
android:text="tv3"
app:layout_flexGrow="1" />
</com.google.android.flexbox.FlexboxLayout>
layout_flexShrink
縮小比例,如果所有子 View 的 layout_flexShrink 屬性都為 1,當空間不足時,都將等比例縮小,如果一個專案的 layout_flexShrink 屬性為0,其他子View都為 1,則空間不足時,layout_flexShrink 屬性為 0 的不縮小,
<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="300dp"
android:layout_height="500dp"
android:background="@android:color/black">
<!--
flex-shrink (縮小比例,超出空間怎么壓縮)
默認: float FLEX_SHRINK_DEFAULT = 1f;
計算方法:
孩子寬度和 = 150 * 3 = 450
450 - 300 = 150 即超出父布局寬度150
tv1最終寬度 = 自身寬度150 - 超出寬度所占比例的寬度150 * (2 / 4) = 75
tv2最終寬度 = 自身寬度150 - 超出寬度所占比例的寬度150 * (1 / 4) = 112.5
tv3最終寬度 = 自身寬度150 - 超出寬度所占比例的寬度150 * (1 / 4) = 112.5
-->
<TextView
android:id="@+id/tv1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_purple"
android:gravity="center"
android:padding="5dp"
android:text="tv1"
android:textColor="@android:color/white"
app:layout_flexShrink="2" />
<TextView
android:id="@+id/tv2"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="#FFC107"
android:gravity="center"
android:padding="5dp"
android:text="tv2"
app:layout_flexShrink="1" />
<TextView
android:id="@+id/tv3"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:gravity="center"
android:padding="5dp"
android:text="tv3"
app:layout_flexShrink="1" />
</com.google.android.flexbox.FlexboxLayout>
layout_alignSelf
子元素對齊,對齊方式,取值和align相同,覆寫align-items,
layout_alignSelf 屬性可以給子元素設定對齊方式,這個屬性的功能和alignItems一樣,
只不過alignItems作用于所有子元素,而 layout_alignSelf 作用于單個子元素,
默認值為auto, 表示繼承alignItems屬性,如果為auto以外的值,則會覆寫alignItems屬性,有以下6種取值:
- auto (default)
- flex_start
- flex_end
- center
- baseline
- stretch
layout_flexBasisPercent
子元素占父元素百分比,layout_flexBasisPercent的值為一個百分比,表示設定子元素的長度為它父容器長度的百分比,如果設定了這個值,那么通過這個屬性計算的值將會覆寫layout_width或者layout_height的值,
但是需要注意,這個值只有設定了父容器的長度時才有效,默認值是-1,
<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="300dp"
android:layout_height="300dp"
android:background="@android:color/black">
<!--
layout_flexBasisPercent
決定了在分配多余空間之前,子元素占據的主軸空間的百分比,
默認為自身大小
-->
<TextView
android:id="@+id/tv1"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_purple"
android:gravity="center"
android:padding="5dp"
android:text="tv1"
android:textColor="@android:color/white"
app:layout_flexBasisPercent="40%" />
<TextView
android:id="@+id/tv2"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:background="#FFC107"
android:gravity="center"
android:padding="5dp"
android:text="tv2"
app:layout_flexBasisPercent="30%" />
<TextView
android:id="@+id/tv3"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:gravity="center"
android:padding="5dp"
android:text="tv3"
app:layout_flexBasisPercent="20%" />
</com.google.android.flexbox.FlexboxLayout>
layout_minWidth / layout_minHeight
這個屬性設定了子 View 的最小的寬和高,在 layout_flexShrink 模式下,再怎么縮小也不會小于這個值
layout_maxWidth / layout_maxHeight
這個屬性設定了子 View 的最大的寬和高,在 layout_flexGrow 模式下,再怎么放大也不會大于這個值
layout_wrapBefore
這個屬性使得子 View 可以強制換行,不管在 main size 剩余空間有多少,這種對于類似 grid 網格布局中特殊設定某一個 item 布局特別有用,默認 false,
參考
- https://github.com/google/flexbox-layout
- https://stackoverflow.com/questions/31250174/css-flexbox-difference-between-align-items-and-align-content
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/254083.html
標籤:其他
上一篇:java.lang.IllegalStateException: Bindings already cleared. 2021-01-28
