*本篇文章已授權(quán)微信公眾號 guolin_blog (郭霖)獨(dú)家發(fā)布
最近一直忙于學(xué)習(xí)后臺開發(fā),很久沒有寫Android的文章了,終于閑下來整理了一篇文章。
前言
FlexboxLayout是去年 Google I/O 上開源的一個布局控件,使得 Android 里的 CSS Flexible Layout模塊也能擁有同樣強(qiáng)大的功能。同時還發(fā)布了強(qiáng)大的ConstraintLayout,感興趣的同學(xué)可以去看看我的上一篇文章Android ConstraintLayout詳解。FlexboxLayout 可以理解為高級的 LinearLayout ,因為這兩個布局都將其子視圖按序排列。二者之間的重要差異在于 FlexboxLayout 具有 “換行” 的特性。同時FlexboxLayout還為RecycleView提供了管理器FlexboxLayoutManager,使得FlexboxLayout更加強(qiáng)大了。
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>
運(yùn)行后的效果如下

好像并沒有換行啊,別急騷年,接下來我們一一介紹FlexboxLayout的一些常用屬性
FlexboxLayout 常用屬性
flexDirection
flexDirection屬性決定主軸項目排列方向。類似LinearLayout 的 vertical 和 horizontal,但是FlexboxLayout更加強(qiáng)大,不僅支持橫向和縱向還可以設(shè)置不同的排列的起點(diǎn)。
row(默認(rèn)值):主軸為水平方向,起點(diǎn)在左端row_reverse:主軸為水平方向,起點(diǎn)在右端。column:主軸為垂直方向,起點(diǎn)在上沿column_reverse:主軸為垂直方向,起點(diǎn)在下沿
我們添加flexDirection屬性,設(shè)置未縱向并且起點(diǎn)在下端,在xml添加屬性
app:flexDirection="column_reverse"

可以看到項目是從底部開始由下而上排列的。
flexWrap
默認(rèn)FlexboxLayout和LinearLayout一樣是不帶換行屬性的,但是flexWrap屬性可以支持換行排列。這就是FlexboxLayout方便的地方了。換行方式有兩種,一種是按項目排列方向換行,一種是反方向換行
nowrap:不換行wrap:按正常方向換行wrap_reverse:按反方向換行
我們設(shè)置按照正常方向換行,添加屬性
app:flexWrap="wrap"

justifyContent
justifyContent屬性定義了項目在主軸上的對齊方式。
flex_start(默認(rèn)值):左對齊flex_end:右對齊center: 居中space_between:兩端對齊,項目之間的間隔都相等。space_around:每個項目兩側(cè)的間隔相等。項目之間的間隔比項目與邊框的間隔大一倍。
默認(rèn)是左對齊的,現(xiàn)在我們設(shè)置右對齊,xml添加屬性
app:justifyContent="flex_end"

如果需要在項目的排列方向上均分剩余的空間怎么辦呢?很簡單space_around屬性就是這樣的,效果如下

alignItems
alignItems屬性定義項目在副軸軸上如何對齊,我們通過一張圖來了解這個屬性比較直觀一點(diǎn)。
flex-start:交叉軸的起點(diǎn)對齊。flex-end:交叉軸的終點(diǎn)對齊。center:交叉軸的中點(diǎn)對齊。baseline: 項目的第一行文字的基線對齊。stretch(默認(rèn)值):如果項目未設(shè)置高度或設(shè)為auto,將占滿整個容器的高度。

這也是為什么我們的每一個項目的高度都是不相同的,但是可以看到前面每個項目的高度都是一樣的,因為默認(rèn)屬性stretch讓每個項目的高度設(shè)置為了填滿容器的高度(這里的高度是指同一軸上的最高高度) 現(xiàn)在我們設(shè)置對齊方式為中心對齊,添加屬性
app:alignItems="center"

可以看到是根據(jù)每個項目的中心對齊,這里單獨(dú)說一下baseline屬性,熟悉ConstraintLayout的同學(xué)應(yīng)該比較好理解這個屬性,其實就是按照項目內(nèi)的文本線來對齊項目。效果如下

可以看到項目對齊是按照項目內(nèi)的文本基線來對齊的。很好理解!需要注意的是項目中如果有的沒有文本基線,那么默認(rèn)他的基線就是左上角也就是起點(diǎn)左右位置

alignContent
alignContent屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。
flex_start:與交叉軸的起點(diǎn)對齊。flex_end:與交叉軸的終點(diǎn)對齊。center:與交叉軸的中點(diǎn)對齊。space_between:與交叉軸兩端對齊,軸線之間的間隔平均分布。space_around:每根軸線兩側(cè)的間隔都相等。所以,軸線之間的間隔比軸線與邊框的間隔大一倍。stretch(默認(rèn)值):軸線占滿整個交叉軸。
alignContent和justifyContent其實里面的屬性值都是一樣的 ,一個是設(shè)置主軸的對齊方式,一個是設(shè)置多個軸的對齊方式,通俗的講可以理解為比如是項目是水平換行,justifyContent就是設(shè)置垂直方向的對齊方式,justifyContent就是設(shè)置水平方向的對齊方式?,F(xiàn)在我們想讓每個項目距離上右下左的距離是一樣的,需要把alignContent和justifyContent都設(shè)置為space_around就可以了,
app:alignContent="space_around"
app:justifyContent="space_around"

子元素屬性
除以上之外,FlexboxLayout不僅有自身的屬性,還可以設(shè)置子元素的屬性。這也是FlexboxLayout能完成聰明布局的原因之一
layout_order
默認(rèn)情況下子元素的排列方式按照文檔流的順序依次排序,而order屬性可以控制排列的順序,負(fù)值在前,正值在后,按照從小到大的順序依次排列。簡而言之就是你可以定義子元素的排列順序。
我們給子元素加上order屬性并且自定義他們的順序

layout_flexGrow
layout_flexGrow 屬性定義項目的放大比例,默認(rèn)為0,即如果存在剩余空間,也不放大。其實就是 LinearLayout 中的weight屬性,如果所有項目的layout_flexGrow 屬性都為1,則它們將等分剩余空間。如果一個項目的layout_flexGrow 屬性為2,其他項目都為1,則前者占據(jù)的剩余空間將比其他項多一倍。

layout_flexShrink
layout_flexShrink 屬性定義了項目的縮小比例,默認(rèn)為1,即如果空間不足,該項目將縮小。如果所有項目的 layout_flexShrink 屬性都為1,當(dāng)空間不足時,都將等比例縮小。如果一個項目的flex-shrink屬性為0,其他項目都為1,則空間不足時,前者不縮小。負(fù)值對該屬性無效。
layout_alignSelf
layout_alignSelf 屬性允許單個子元素有與其他子元素不一樣的對齊方式,可覆蓋 alignItems 屬性。默認(rèn)值為auto,表示繼承父元素的alignItems 屬性,如果沒有父元素,則等同于stretch。
auto (default)flex_startflex_endcenterbaselinestretch
該屬性可能取6個值,除了auto,其他都與align_items屬性完全一致,我們設(shè)置alignItems為flex_start屬性,其中一個子元素設(shè)置layout_alignSelf屬性為baseline

可以看到第三個子元素對齊方式和其他的元素對齊方式明顯不一樣,
baseline的基線是第一個元素的 baseline基線。
layout_flexBasisPercent
layout_flexBasisPercent 屬性定義了在分配多余空間之前,子元素占據(jù)的主軸空間的百分比。它的默認(rèn)值為auto,即子元素的本來大小。
我們設(shè)置第一個和第三個都占據(jù)的主軸空間的80%,給子元素添加屬性
app:layout_flexBasisPercent="80%"

FlexboxLayout的屬性基本講解完了,如果一臉懵逼那么請 看第二遍。FlexboxLayout能幫你完成各種你需要的布局,可謂LinearLayout的加強(qiáng)版。比如我們需要做一個類似于Tag標(biāo)簽的布局,那么FlexboxLayout能幫你輕輕松松實現(xiàn)。這里需要用到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添加布局管理器,并設(shè)置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);
}
這里是設(shè)置的子元素的屬性,設(shè)置的屬性可以參考上面的介紹。效果圖如下

輕輕松松實現(xiàn)了Tag標(biāo)簽的效果,是不是很簡單,同樣的方式我們還可以實現(xiàn)一個圖片流布局效果圖如下

FlexboxLayout的使用現(xiàn)在已經(jīng)講解完了,相信各位對這個控件的強(qiáng)大已經(jīng)有所了解了,不妨親自動手感受下這個控件的強(qiáng)大。GOOGLE開放了越來越多的控件和開發(fā)輔助工具,對于開發(fā)者的我們來說當(dāng)然是好的。當(dāng)然我們自己也要保持一顆熱愛學(xué)習(xí)的心,不要抗拒新的東西,不斷學(xué)習(xí) 充實自己! 知行合一
THE END ~~~