FlexboxLayout全攻略(Google官方灵活实现流式布局控件)
一、FlexboxLayout是什么
FlexboxLayout是Google開源的一個強大的控件,直接繼承ViewGroup,效果類似于加強版的LinearLayout,但與LinearLayout并無關聯。
官方原話是:
FlexboxLayout is a library project which brings the similar capabilities of CSS Flexible Box Layout Module to Android.
意思是:FlexBoxLayout是為Android帶來了與 CSS Flexible Box Layout(CSS 彈性盒子)相似功能的庫。
Github地址:https://github.com/google/flexbox-layout
二、如何使用FlexboxLayout
FlexBoxLayout有非常多的屬性,下面一一驗證各個屬性的作用
引用依賴
dependencies {implementation 'com.google.android:flexbox:1.1.0' }如果還沒用上AndroidX:
dependencies {implementation 'com.google.android:flexbox:1.0.0' }在布局中簡單使用
<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="推送和即時通訊"/><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="旅行——在路上" /><TextViewstyle="@style/TextStyle"android:text="復仇者聯盟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>運行看一下效果:
可以看到內容雖然出來了,但都擠在同一行了,這顯然并不是我要的效果。
那么接下來就該FlexboxLayout屬性們出來救場了:
三、FlexboxLayout屬性介紹
FlexboxLayout直接屬性
1. app:flexWrap=“nowrap”
簡單來說,該屬性表示是否換行和換行的方向。
由上圖可見,flexWrap屬性一共有三個枚舉值,分別是nowrap、wrap和wrap_reverse
- nowrap:單行顯示,不換行,默認就是這個屬性。
- wrap:當內容超過一行時,自動換行。效果:
- wrap_reverse :反向換行(下一行內容在當前行之上)
2. app:flexDirection=“row”
該屬性表示主軸的方向,子元素的排列按照軸線方向依次添加。
再看一下源碼,可見flexDirection的枚舉值有row和row_reverse,column和column_reverse
-
row : 主軸方向按水平(行)方向排版,默認就是這個屬性。效果:
-
row_reverse : 主軸方向按水平(行)方向反向排版。效果:
由效果圖可見,row是從左向右繪制,row_reverse是row的反向,也就是從右向左繪制啦。同理column也是一樣。 -
column : 主軸方向按豎直(列)方向排版。效果:
-
column_reverse : 主軸方向按豎直(列)方向反向排版(從下向上)。
3. app:justifyContent=“flex_start”
關于這個屬性,官方有一段說明:
<!-- 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. -->
作用是控制元素在主軸上的對齊方式,需要配合flexDirection或flexWrap屬性來使用。
看一下源碼,可見app:justifyContent屬性有flex_start、flex_end、center、space_between、space_around和space_evenly6個枚舉值。
下面把以上兩個屬性改為:
app:flexWrap="wrap"app:flexDirection="row"來看效果。
-
flex_start: 左對齊,默認值。
-
flex_end : 右對齊。
-
center:居中對齊。
-
space_between: 兩端對齊。
-
space_around : 分散對齊。
-
space_evenly:子元素在一行內均勻分布空間。
4. app:alignItems=“stretch”
該屬性表示元素在每條軸線上的對齊方式。
注意:如果設置了alignContent,且值不為stretch,那么該屬性失效。
app:alignItems屬性有flex_start、flex_end、center、baseline和stretch
下面把FlexBoxLayout指定一個高度,并為TextView添加不同的padding來看效果。
- stretch: 默認值,如果子元素未設置高度,則沾滿父布局高度。
- flex_start :頂端對齊。
- flex_end :底端對齊。
- center : 居中對齊。
- baseline :按照第一個元素的基線對齊。
下面這張圖片可以很直觀的表達這個屬性的作用。圖片來源
5. app:alignContent=“stretch”
該屬性表示每條軸線在整個布局中的對齊方式。
app:alignContent屬性有flex_start、flex_end、center、space_between、space_around和stretch6個枚舉值。
-
stretch:默認值,軸線占滿整個父布局。
-
flex_start:頂部對齊所有軸線。
-
flex_end:底部對齊所有軸線。
-
center:居中對齊所有軸線。
-
space_between:兩端對齊所有軸線。
-
space_around:分散對齊所有軸線。
插一句嘴,軸線方向可以由flexDirection屬性來指定,注意屬性搭配,舉一反三。
6. dividerDrawable (reference)
水平和豎直方向分割線。
7. dividerDrawableHorizontal / dividerDrawableVertical (reference)
水平/豎直方向分割線。
8. showDivider
顯示水平和豎直方向分割線方式。
枚舉值有:
-
none
不顯示。 -
beginning
-
middle
-
end
9. showDividerHorizontal / showDividerVertical
顯示水平/豎直方向分割線方式。
FlexboxLayout子元素屬性
1. app:layout_order=“1”
指定子元素排序優先級,值越小越排在前面,默認值為1。設置值類型為float。
如圖,藍牙TextView元素在xml中排序為第二個,但給它的layout_order屬性指定為2,藍牙排名到最后一位了。
2. app:layout_flexGrow=“0”
分配同一軸線剩余控件所占權重,默認值為0,表示不參與分配。用法類似于LinearLayout的weight,不過weight分配的是整個父布局控件,而layout_flexGrow分配的是同一行/列的剩余空間。
舉個例子:將藍牙的layout_flexGrow設為1,程序的layout_flexGrow屬性設為2
如圖,藍牙與程序都參與到了剩余空間分配,由于程序設置的權重為2,所以比藍牙多分配了一倍的空間。
3. app:layout_flexShrink=“0”
子元素縮放比例,如果設置了換行(flexWrap=“wrap或wrap_reverse”)則該屬性無效。
設置值類型為float,0表示不縮放,數值越大,縮放比例越大,默認為1,負值無效。
例子:推送和即時通訊設置為0(不縮放),旅行——在路上設置為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.-->表示子元素長度是其父布局長度的百分比,設置了元素的layout_flexBasisPercent將覆蓋子元素原本長度,默認值為-1。要注意的是,只有具體設置了父布局的長度才能生效。
設置的值為百分數,例如50%。
例子:將第一個元素寬度設置為父布局的50%(app:layout_flexBasisPercent="50%")。
5. app:layout_alignSelf=“auto”
所用與alignItems屬性一樣,不同點是alignItems設置的是所有元素,而layout_alignSelf作用于單個元素。
需要注意的一點是,若父布局設置了alignContent,并且枚舉值不為stretch,則改屬性失效。
layout_alignSelf的枚舉值有auto,flex_start,flex_end,center,baseline和stretch,作用與alignItems屬性相同。
例子:將推送和即時通訊設置為flex_start,藍牙的layout_alignSelf設置為stretch。效果:
6.app:layout_wrapBefore=“false”
強制換行,默認為false。
若為子元素設置了layout_wrapBefore屬性為false,那么這個子元素將重新另起一行。
例:為藍牙設置layout_wrapBefore屬性為true
7. layout_minWidth / layout_minHeight
限制 FlexboxLayout的子元素(寬或高)不會小于最小值,無論layout_flexShrink屬性為多少,子元素不會被縮小到小于設置的這個最小值。
8. layout_maxWidth / layout_maxHeight
限制 FlexboxLayout的子元素(寬或高)不會大于最小值,無論layout_flexGrow屬性為多少,子元素不會被放大到大于于設置的這個最小值。
小結
FlexBoxLayout的常用屬性就這么多了,靈活運用這些屬性的搭配可以達到非常靈活的效果。
四、與RecyclerView配合使用
官方不僅提供了FlexboxLayout布局,還提供了FlexboxLayoutManager來與RecyclerView配合使用。
The second one is FlexboxLayoutManager that can be used within RecyclerView.
雖然RecyclerView之前也有StaggeredGridLayoutManager來提供瀑布流效果,但還是要指定行/列數、相比之下,FlexboxLayoutManager更加靈活,且應用場景也不盡相同。
下面將RecyclerView的layoutManager設置成FlexboxLayoutManager
先看一下效果:
白色背景為設置了FlexboxLayoutManager的RecyclerView,綠色背景為FlexboxLayout,可見FlexboxLayoutManagery與FlexboxLayout可以達到相同的效果。
主要代碼:
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.");}可見,FlexboxLayoutManager不支持alignContent 屬性,如果強行設置則會報出以下異常。
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還有哪些使用的不同呢?官方這張表給出了很好地說明。
| 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 |
五、實踐
這樣的流失布局,如果在項目中碰到,貌似只能自定義View,或者尋求別人寫好的庫了。
但有了FlexboxLayout之后可以完美解決。
以上例子可以參考:https://gitee.com/zhengyz_0430/CloudReaderKotlin
六、總結
空談誤國,實干興邦
要真想理解FlexboxLayout的各個屬性,自己實踐和閱讀源碼是必不可少的,話不多說,還是多多動手實踐吧。
FlexboxLayout與FlexboxLayoutManager可以完美實現靈活的流式布局,并且該庫已經添加到androidX了,Google大大為我們的開發真是操碎了心啊。
參考
https://blog.csdn.net/tabolt/article/details/51799226
https://www.jianshu.com/p/3c471953e36d
https://www.oschina.net/news/73442/google-flexbox-layout
總結
以上是生活随笔為你收集整理的FlexboxLayout全攻略(Google官方灵活实现流式布局控件)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SSM+老年人社区服务平台 毕业设计-附
- 下一篇: 洛克人java下载_洛克人-威利博士末日