FlexboxLayout全攻略(Google官方灵活实现流式布局控件)
一、FlexboxLayout是什么
FlexboxLayout是Google開(kāi)源的一個(gè)強(qiáng)大的控件,直接繼承ViewGroup,效果類似于加強(qiáng)版的LinearLayout,但與LinearLayout并無(wú)關(guān)聯(lián)。
官方原話是:
FlexboxLayout is a library project which brings the similar capabilities of CSS Flexible Box Layout Module to Android.
意思是:FlexBoxLayout是為Android帶來(lái)了與 CSS Flexible Box Layout(CSS 彈性盒子)相似功能的庫(kù)。
Github地址:https://github.com/google/flexbox-layout
二、如何使用FlexboxLayout
FlexBoxLayout有非常多的屬性,下面一一驗(yàn)證各個(gè)屬性的作用
引用依賴
dependencies {implementation 'com.google.android:flexbox:1.1.0' }如果還沒(méi)用上AndroidX:
dependencies {implementation 'com.google.android:flexbox:1.0.0' }在布局中簡(jiǎn)單使用
<com.google.android.flexbox.FlexboxLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/colorPrimary"app:flexWrap="wrap"><TextViewstyle="@style/TextStyle"android:text="推送和即時(shí)通訊"/><TextViewstyle="@style/TextStyle"android:text="藍(lán)牙" /><TextViewstyle="@style/TextStyle"android:text="程序員"/><TextViewstyle="@style/TextStyle"android:text="影視天堂" /><TextViewstyle="@style/TextStyle"android:text="郭德綱" /><TextViewstyle="@style/TextStyle"android:text="旅行——在路上" /><TextViewstyle="@style/TextStyle"android:text="復(fù)仇者聯(lián)盟4" /></com.google.android.flexbox.FlexboxLayout>TextStyle如下:
<style name="TextStyle"><item name="android:layout_margin">5dp</item><item name="android:layout_width">wrap_content</item><item name="android:layout_height">wrap_content</item><item name="android:background">@drawable/shape_pink_border</item><item name="android:ellipsize">end</item><item name="android:maxLines">1</item><item name="android:padding">8dp</item><item name="android:textColor">@android:color/white</item></style>shape_pink_border文件:
<shape xmlns:android="http://schemas.android.com/apk/res/android"><corners android:radius="8dp"/><stroke android:width="1dp" android:color="@android:color/holo_red_light"/> </shape>運(yùn)行看一下效果:
可以看到內(nèi)容雖然出來(lái)了,但都擠在同一行了,這顯然并不是我要的效果。
那么接下來(lái)就該FlexboxLayout屬性們出來(lái)救場(chǎng)了:
三、FlexboxLayout屬性介紹
FlexboxLayout直接屬性
1. app:flexWrap=“nowrap”
簡(jiǎn)單來(lái)說(shuō),該屬性表示是否換行和換行的方向。
由上圖可見(jiàn),flexWrap屬性一共有三個(gè)枚舉值,分別是nowrap、wrap和wrap_reverse
- nowrap:單行顯示,不換行,默認(rèn)就是這個(gè)屬性。
- wrap:當(dāng)內(nèi)容超過(guò)一行時(shí),自動(dòng)換行。效果:
- wrap_reverse :反向換行(下一行內(nèi)容在當(dāng)前行之上)
2. app:flexDirection=“row”
該屬性表示主軸的方向,子元素的排列按照軸線方向依次添加。
再看一下源碼,可見(jiàn)flexDirection的枚舉值有row和row_reverse,column和column_reverse
-
row : 主軸方向按水平(行)方向排版,默認(rèn)就是這個(gè)屬性。效果:
-
row_reverse : 主軸方向按水平(行)方向反向排版。效果:
由效果圖可見(jiàn),row是從左向右繪制,row_reverse是row的反向,也就是從右向左繪制啦。同理column也是一樣。 -
column : 主軸方向按豎直(列)方向排版。效果:
-
column_reverse : 主軸方向按豎直(列)方向反向排版(從下向上)。
3. app:justifyContent=“flex_start”
關(guān)于這個(gè)屬性,官方有一段說(shuō)明:
<!-- Omitting flex-flow property since it's reflected in the parent flex container. Set the flexDirection and/or flexWrap to the parent flex container explicitly if you want to use the flex-flow similar way to the web. -->
作用是控制元素在主軸上的對(duì)齊方式,需要配合flexDirection或flexWrap屬性來(lái)使用。
看一下源碼,可見(jiàn)app:justifyContent屬性有flex_start、flex_end、center、space_between、space_around和space_evenly6個(gè)枚舉值。
下面把以上兩個(gè)屬性改為:
app:flexWrap="wrap"app:flexDirection="row"來(lái)看效果。
-
flex_start: 左對(duì)齊,默認(rèn)值。
-
flex_end : 右對(duì)齊。
-
center:居中對(duì)齊。
-
space_between: 兩端對(duì)齊。
-
space_around : 分散對(duì)齊。
-
space_evenly:子元素在一行內(nèi)均勻分布空間。
4. app:alignItems=“stretch”
該屬性表示元素在每條軸線上的對(duì)齊方式。
注意:如果設(shè)置了alignContent,且值不為stretch,那么該屬性失效。
app:alignItems屬性有flex_start、flex_end、center、baseline和stretch
下面把FlexBoxLayout指定一個(gè)高度,并為T(mén)extView添加不同的padding來(lái)看效果。
- stretch: 默認(rèn)值,如果子元素未設(shè)置高度,則沾滿父布局高度。
- flex_start :頂端對(duì)齊。
- flex_end :底端對(duì)齊。
- center : 居中對(duì)齊。
- baseline :按照第一個(gè)元素的基線對(duì)齊。
下面這張圖片可以很直觀的表達(dá)這個(gè)屬性的作用。圖片來(lái)源
5. app:alignContent=“stretch”
該屬性表示每條軸線在整個(gè)布局中的對(duì)齊方式。
app:alignContent屬性有flex_start、flex_end、center、space_between、space_around和stretch6個(gè)枚舉值。
-
stretch:默認(rèn)值,軸線占滿整個(gè)父布局。
-
flex_start:頂部對(duì)齊所有軸線。
-
flex_end:底部對(duì)齊所有軸線。
-
center:居中對(duì)齊所有軸線。
-
space_between:兩端對(duì)齊所有軸線。
-
space_around:分散對(duì)齊所有軸線。
插一句嘴,軸線方向可以由flexDirection屬性來(lái)指定,注意屬性搭配,舉一反三。
6. dividerDrawable (reference)
水平和豎直方向分割線。
7. dividerDrawableHorizontal / dividerDrawableVertical (reference)
水平/豎直方向分割線。
8. showDivider
顯示水平和豎直方向分割線方式。
枚舉值有:
-
none
不顯示。 -
beginning
-
middle
-
end
9. showDividerHorizontal / showDividerVertical
顯示水平/豎直方向分割線方式。
FlexboxLayout子元素屬性
1. app:layout_order=“1”
指定子元素排序優(yōu)先級(jí),值越小越排在前面,默認(rèn)值為1。設(shè)置值類型為float。
如圖,藍(lán)牙TextView元素在xml中排序?yàn)榈诙€(gè),但給它的layout_order屬性指定為2,藍(lán)牙排名到最后一位了。
2. app:layout_flexGrow=“0”
分配同一軸線剩余控件所占權(quán)重,默認(rèn)值為0,表示不參與分配。用法類似于LinearLayout的weight,不過(guò)weight分配的是整個(gè)父布局控件,而layout_flexGrow分配的是同一行/列的剩余空間。
舉個(gè)例子:將藍(lán)牙的layout_flexGrow設(shè)為1,程序的layout_flexGrow屬性設(shè)為2
如圖,藍(lán)牙與程序都參與到了剩余空間分配,由于程序設(shè)置的權(quán)重為2,所以比藍(lán)牙多分配了一倍的空間。
3. app:layout_flexShrink=“0”
子元素縮放比例,如果設(shè)置了換行(flexWrap=“wrap或wrap_reverse”)則該屬性無(wú)效。
設(shè)置值類型為float,0表示不縮放,數(shù)值越大,縮放比例越大,默認(rèn)為1,負(fù)值無(wú)效。
例子:推送和即時(shí)通訊設(shè)置為0(不縮放),旅行——在路上設(shè)置為2(雙倍縮放)
4. app:layout_flexBasisPercent="-1"
官方解釋:
<!--The initial length in a percentage format relative to its parent. This is similar to theflex-basis property in the original CSS specification.(https://www.w3.org/TR/css-flexbox-1/#flex-basis-property)But unlike the flex-basis property, this attribute only accepts a value in fraction(percentage), whereas flex-basis property accepts width values such as 1em, 10px andthe 'content' string.But specifying initial fixed width values can be done by specifying width values inlayout_width (or layout_height, varies depending on the flexDirection). Also the sameeffect can be done by specifying "wrap_content" in layout_width (or layout_height) ifdevelopers want to achieve the same effect as 'content'.Thus, this attribute only accepts fraction values, which can't be done throughlayout_width (or layout_height) for simplicity.-->表示子元素長(zhǎng)度是其父布局長(zhǎng)度的百分比,設(shè)置了元素的layout_flexBasisPercent將覆蓋子元素原本長(zhǎng)度,默認(rèn)值為-1。要注意的是,只有具體設(shè)置了父布局的長(zhǎng)度才能生效。
設(shè)置的值為百分?jǐn)?shù),例如50%。
例子:將第一個(gè)元素寬度設(shè)置為父布局的50%(app:layout_flexBasisPercent="50%")。
5. app:layout_alignSelf=“auto”
所用與alignItems屬性一樣,不同點(diǎn)是alignItems設(shè)置的是所有元素,而layout_alignSelf作用于單個(gè)元素。
需要注意的一點(diǎn)是,若父布局設(shè)置了alignContent,并且枚舉值不為stretch,則改屬性失效。
layout_alignSelf的枚舉值有auto,flex_start,flex_end,center,baseline和stretch,作用與alignItems屬性相同。
例子:將推送和即時(shí)通訊設(shè)置為flex_start,藍(lán)牙的layout_alignSelf設(shè)置為stretch。效果:
6.app:layout_wrapBefore=“false”
強(qiáng)制換行,默認(rèn)為false。
若為子元素設(shè)置了layout_wrapBefore屬性為false,那么這個(gè)子元素將重新另起一行。
例:為藍(lán)牙設(shè)置layout_wrapBefore屬性為true
7. layout_minWidth / layout_minHeight
限制 FlexboxLayout的子元素(寬或高)不會(huì)小于最小值,無(wú)論layout_flexShrink屬性為多少,子元素不會(huì)被縮小到小于設(shè)置的這個(gè)最小值。
8. layout_maxWidth / layout_maxHeight
限制 FlexboxLayout的子元素(寬或高)不會(huì)大于最小值,無(wú)論layout_flexGrow屬性為多少,子元素不會(huì)被放大到大于于設(shè)置的這個(gè)最小值。
小結(jié)
FlexBoxLayout的常用屬性就這么多了,靈活運(yùn)用這些屬性的搭配可以達(dá)到非常靈活的效果。
四、與RecyclerView配合使用
官方不僅提供了FlexboxLayout布局,還提供了FlexboxLayoutManager來(lái)與RecyclerView配合使用。
The second one is FlexboxLayoutManager that can be used within RecyclerView.
雖然RecyclerView之前也有StaggeredGridLayoutManager來(lái)提供瀑布流效果,但還是要指定行/列數(shù)、相比之下,FlexboxLayoutManager更加靈活,且應(yīng)用場(chǎng)景也不盡相同。
下面將RecyclerView的layoutManager設(shè)置成FlexboxLayoutManager
先看一下效果:
白色背景為設(shè)置了FlexboxLayoutManager的RecyclerView,綠色背景為FlexboxLayout,可見(jiàn)FlexboxLayoutManagery與FlexboxLayout可以達(dá)到相同的效果。
主要代碼:
val flexboxLayoutManager = FlexboxLayoutManager(this)flexboxLayoutManager.flexWrap = FlexWrap.WRAPflexboxLayoutManager.flexDirection = FlexDirection.ROWflexboxLayoutManager.justifyContent = JustifyContent.FLEX_STARTflexboxLayoutManager.alignItems = AlignItems.FLEX_START//flexboxLayoutManager.alignContent = AlignContent.FLEX_STARTval adapter = FlexAdapter()initData(adapter)rv_flex.layoutManager = flexboxLayoutManagerrv_flex.adapter = adapter注意:flexboxLayoutManager.alignContent,FlexboxLayoutManager不支持alignContent 屬性
看一下setAlignContent的源碼:
@Overridepublic void setAlignContent(@AlignContent int alignContent) {throw new UnsupportedOperationException("Setting the alignContent in the "+ "FlexboxLayoutManager is not supported. Use FlexboxLayout "+ "if you need to use this attribute.");}可見(jiàn),FlexboxLayoutManager不支持alignContent 屬性,如果強(qiáng)行設(shè)置則會(huì)報(bào)出以下異常。
Caused by: java.lang.UnsupportedOperationException: Setting the alignContent in the FlexboxLayoutManager is not supported. Use FlexboxLayout if you need to use this attribute.Demo源碼
那么FlexboxLayoutManager和FlexboxLayout還有哪些使用的不同呢?官方這張表給出了很好地說(shuō)明。
| 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 |
五、實(shí)踐
這樣的流失布局,如果在項(xiàng)目中碰到,貌似只能自定義View,或者尋求別人寫(xiě)好的庫(kù)了。
但有了FlexboxLayout之后可以完美解決。
以上例子可以參考:https://gitee.com/zhengyz_0430/CloudReaderKotlin
六、總結(jié)
空談?wù)`國(guó),實(shí)干興邦
要真想理解FlexboxLayout的各個(gè)屬性,自己實(shí)踐和閱讀源碼是必不可少的,話不多說(shuō),還是多多動(dòng)手實(shí)踐吧。
FlexboxLayout與FlexboxLayoutManager可以完美實(shí)現(xiàn)靈活的流式布局,并且該庫(kù)已經(jīng)添加到androidX了,Google大大為我們的開(kāi)發(fā)真是操碎了心啊。
參考
https://blog.csdn.net/tabolt/article/details/51799226
https://www.jianshu.com/p/3c471953e36d
https://www.oschina.net/news/73442/google-flexbox-layout
總結(jié)
以上是生活随笔為你收集整理的FlexboxLayout全攻略(Google官方灵活实现流式布局控件)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SSM+老年人社区服务平台 毕业设计-附
- 下一篇: 洛克人java下载_洛克人-威利博士末日