Android FlexboxLayout佈局屬性詳解
FlexboxLayout
是Google I/O
大會上開源的一個佈局控制元件,使得 Android
裡的佈局能像 CSS
中的Flexible屬性一樣
能擁有同樣強大的功能。FlexboxLayout
可以理解為高階的 LinearLayout
,因為這兩個佈局都將其子檢視按序排列。二者之間的重要差異在於 FlexboxLayout
具有 “換行” 的特性。同時FlexboxLayout
還為RecycleView
提供了管理器FlexboxLayoutManager
,使得FlexboxLayout
更加強大了。
FlexboxLayout的
開源地址:https://github.com/google/flexbox-layout
文章Demo的地址:https://github.com/Hemumu/FlexboxLayoutDemo
使用
專案中新增依賴
dependencies {
compile 'com.google.android:flexbox:0.2.6'
}
如果是在RecycleView
中使用則新增
dependencies {
compile 'com.google.android:flexbox:0.3.0-alpha3'
}
Alpha
版本包括RecyclerView
的整合
XML中添加布局
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.qyhl2.flexboxlayoutdemo.MainActivity"> <com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/flexboxLayout" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginBottom="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" app:layout_constraintVertical_bias="0.5"> <TextView android:id="@+id/textview1" android:layout_width="120dp" android:layout_height="20dp" android:layout_margin="2dp" android:background="#43eeff" android:gravity="center" android:text="1" /> <TextView android:id="@+id/textview2" android:layout_width="120dp" android:layout_height="60dp" android:layout_margin="2dp" android:background="#ef3344" android:gravity="center" android:text="2" /> <TextView android:id="@+id/textview3" android:layout_width="120dp" android:layout_height="90dp" android:layout_margin="2dp" android:background="#ee998f" android:gravity="center" android:text="3" /> <TextView android:id="@+id/textview4" android:layout_width="120dp" android:layout_height="100dp" android:layout_margin="2dp" android:background="#eeff22" android:gravity="center" android:text="4" /> <TextView android:id="@+id/textview5" android:layout_width="120dp" android:layout_height="80dp" android:layout_margin="2dp" android:background="#3322ff" android:gravity="center" android:text="5" /> </com.google.android.flexbox.FlexboxLayout>
執行後的效果如下
好像並沒有換行啊,別急騷年,接下來我們一一介紹FlexboxLayout
的一些常用屬性
FlexboxLayout 常用屬性
flexDirection
flexDirection
屬性決定主軸專案排列方向。類似LinearLayout
的 vertical
和 horizontal
,但是FlexboxLayout
更加強大,不僅支援橫向和縱向還可以設定不同的排列的起點。
-
row
(預設值):主軸為水平方向,起點在左端 -
row_reverse
:主軸為水平方向,起點在右端。 -
column
:主軸為垂直方向,起點在上沿 -
column_reverse
我們新增flexDirection
屬性,設定未縱向並且起點在下端,在xml新增屬性
app:flexDirection="column_reverse"
可以看到專案是從底部開始由下而上排列的。
flexWrap
預設FlexboxLayout
和LinearLayout
一樣是不帶換行屬性的,但是flexWrap
屬性可以支援換行排列。這就是FlexboxLayout
方便的地方了。換行方式有兩種,一種是按專案排列方向換行,一種是反方向換行
-
nowrap
:不換行 -
wrap
:按正常方向換行 -
wrap_reverse
:按反方向換行
我們設定按照正常方向換行,新增屬性
app:flexWrap="wrap"
justifyContent
justifyContent
屬性定義了專案在主軸上的對齊方式。
-
flex_start
(預設值):左對齊 -
flex_end
:右對齊 -
center
: 居中 -
space_between
:兩端對齊,專案之間的間隔都相等。 -
space_around
:每個專案兩側的間隔相等。專案之間的間隔比專案與邊框的間隔大一倍。
預設是左對齊的,現在我們設定右對齊,xml新增屬性
app:justifyContent="flex_end"
如果需要在專案的排列方向上均分剩餘的空間怎麼辦呢?很簡單space_around
屬性就是這樣的,效果如下
alignItems
alignItems
屬性定義專案在副軸軸上如何對齊,我們通過一張圖來了解這個屬性比較直觀一點。
-
flex-start
:交叉軸的起點對齊。 -
flex-end
:交叉軸的終點對齊。 -
center
:交叉軸的中點對齊。 -
baseline
: 專案的第一行文字的基線對齊。 -
stretch
(預設值):如果專案未設定高度或設為auto,將佔滿整個容器的高度。
這也是為什麼我們的每一個專案的高度都是不相同的,但是可以看到前面每個專案的高度都是一樣的,因為預設屬性stretch
讓每個專案的高度設定為了填滿容器的高度(這裡的高度是指同一軸上的最高高度) 現在我們設定對齊方式為中心對齊,新增屬性
app:alignItems="center"
可以看到是根據每個專案的中心對齊,這裡單獨說一下baseline
屬性,熟悉ConstraintLayout
的同學應該比較好理解這個屬性,其實就是按照專案內的文字線來對齊專案。效果如下
可以看到專案對齊是按照專案內的文字基線來對齊的。很好理解!需要注意的是專案中如果有的沒有文字基線,那麼預設他的基線就是左上角也就是起點左右位置
alignContent
alignContent
屬性定義了多根軸線的對齊方式。如果專案只有一根軸線,該屬性不起作用。
-
flex_start
:與交叉軸的起點對齊。 -
flex_end
:與交叉軸的終點對齊。 -
center
:與交叉軸的中點對齊。 -
space_between
:與交叉軸兩端對齊,軸線之間的間隔平均分佈。 -
space_around
:每根軸線兩側的間隔都相等。所以,軸線之間的間隔比軸線與邊框的間隔大一倍。 -
stretch
(預設值):軸線佔滿整個交叉軸。
alignContent
和justifyContent
其實裡面的屬性值都是一樣的 ,justifyContent
是設定主軸的對齊方式,alignContent
是設定多個軸的對齊方式,通俗的講可以理解為比如是專案是水平換行,justifyContent
就是設定垂直方向的對齊方式,alignContent
就是設定水平方向的對齊方式。現在我們想讓每個專案距離上右下左的距離是一樣的,需要把alignContent
和justifyContent
都設定為space_around
就可以了,
app:alignContent="space_around"
app:justifyContent="space_around"
子元素屬性
除以上之外,FlexboxLayout
不僅有自身的屬性,還可以設定子元素的屬性。這也是FlexboxLayout
能完成聰明佈局的原因之一
layout_order
預設情況下子元素的排列方式按照文件流的順序依次排序,而order
屬性可以控制排列的順序,負值在前,正值在後,按照從小到大的順序依次排列。簡而言之就是你可以定義子元素的排列順序。
我們給子元素加上order屬性
並且自定義他們的順序
layout_flexGrow
layout_flexGrow
屬性定義專案的放大比例,預設為0,即如果存在剩餘空間,也不放大。其實就是 LinearLayout
中的weight
屬性,如果所有專案的layout_flexGrow
屬性都為1,則它們將等分剩餘空間。如果一個專案的layout_flexGrow
屬性為2,其他專案都為1,則前者佔據的剩餘空間將比其他項多一倍。
layout_flexShrink
layout_flexShrink
屬性定義了專案的縮小比例,預設為1,即如果空間不足,該專案將縮小。如果所有專案的 layout_flexShrink
屬性都為1,當空間不足時,都將等比例縮小。如果一個專案的flex-shrink
屬性為0,其他專案都為1,則空間不足時,前者不縮小。負值對該屬性無效。
layout_alignSelf
layout_alignSelf
屬性允許單個子元素有與其他子元素不一樣的對齊方式,可覆蓋 alignItems
屬性。預設值為auto
,表示繼承父元素的alignItems
屬性,如果沒有父元素,則等同於stretch
。
-
auto (default)
-
flex_start
-
flex_end
-
center
-
baseline
-
stretch
該屬性可能取6個值,除了auto
,其他都與align_items
屬性完全一致,我們設定alignItems
為flex_start
屬性,其中一個子元素設定layout_alignSelf
屬性為baseline
可以看到第三個子元素對齊方式和其他的元素對齊方式明顯不一樣,baseline
的基線是第一個元素的 baseline
基線。
layout_flexBasisPercent
layout_flexBasisPercent
屬性定義了在分配多餘空間之前,子元素佔據的主軸空間的百分比。它的預設值為auto,即子元素的本來大小。
我們設定第一個和第三個都佔據的主軸空間的80%
,給子元素新增屬性
app:layout_flexBasisPercent="80%"
FlexboxLayout
的屬性基本講解完了,如果一臉懵逼那麼請 看第二遍。FlexboxLayout
能幫你完成各種你需要的佈局,可謂LinearLayout
的加強版。比如我們需要做一個類似於Tag
標籤的佈局,那麼FlexboxLayout
能幫你輕輕鬆鬆實現。這裡需要用到FlexboxLayoutManager
,也就是FlexboxLayout
對RecycleView
提供的佈局管理器
佈局中新增RecycleView
<android.support.v7.widget.RecyclerView
android:id="@+id/test_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
</android.support.v7.widget.RecyclerView>
程式碼中對RecycleView
添加布局管理器,並設定FlexboxLayout
的主屬性
mRecyclerView = (RecyclerView)findViewById(R.id.test_recyclerView);
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);
layoutManager.setFlexDirection(FlexDirection.ROW);
layoutManager.setAlignItems(AlignItems.STRETCH);
layoutManager.setJustifyContent(JustifyContent.FLEX_START);
mRecyclerView.setLayoutManager(layoutManager);
在adapter
繫結view
的時候加入下面的程式碼
ViewGroup.LayoutParams lp = te.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
FlexboxLayoutManager.LayoutParams flexboxLp = (FlexboxLayoutManager.LayoutParams) lp;
flexboxLp.setFlexGrow(1.0f);
}
這裡是設定的子元素的屬性,設定的屬性可以參考上面的介紹。效果圖如下
輕輕鬆鬆實現了Tag
標籤的效果,是不是很簡單,同樣的方式我們還可以實現一個圖片流佈局效果圖如下
FlexboxLayout
的使用現在已經講解完了,相信各位對這個控制元件的強大已經有所瞭解了,不妨親自動手感受下這個控制元件的強大。
注:本文是轉載原文連結:https://www.jianshu.com/p/b3a9c4a99053