在去年的Google I/O大會上碘橘,Google發(fā)布了 ConstraintLayout他使我們能夠使用一個平面的視圖層次來構(gòu)建復(fù)雜的界面布局畜埋。android studio的視圖編輯器也對其實現(xiàn)了完整支持熙掺。
與此同時匪补,Google開源了FlexboxLayout 他與CSS Flexible 布局模塊具有相同的功能佑钾。接下來的例子我們將使用FlexboxLayout實現(xiàn)一些特殊的功能西疤。
你可以把FlexboxLayout理解成一個高級的LinearLayout,他和LinearLayout一樣都是在水平和垂直方向上按順序放置子view,他與LinearLayout最大的不同在于FlexboxLayout 有一個wrapping功能。當(dāng)你增加flexWrap="wrap"屬性后休溶,假如在當(dāng)前方向上沒有足夠的空間可以放置新的子view代赁,他會在新的一行上放置子view。
同一布局適配多種屏幕尺寸
我們想要在水平方向依次放置一些view兽掰,假如有效的空間發(fā)生變化后(不同的手機設(shè)備芭碍、手機方向發(fā)生改變、多窗口模式導(dǎo)致的界面重繪等)我們想要在新的一行繼續(xù)放置上一行沒有空閑空間顯示的view孽尽。
如果你使用傳統(tǒng)的布局方式來實現(xiàn)這個功能,如LinearLayout窖壕、RelativeLayout你需要定義多個 DP-bucket 布局(例如layout-600dp, layout-720dp, layout-1020dp)來處理多屏幕尺寸的問題。但是上邊的對話框只使用了一個FlexboxLayout就實現(xiàn)了這個功能杉女。
這個例子中使用了上邊提到的flexWrap="wrap"屬性
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexwrap="wrap">
......```
使用flexwrap="wrap"你將得到下邊的布局效果瞻讽,而不會是像LinearLayout那樣從父布局中溢出
![](http://upload-images.jianshu.io/upload_images/2758471-39b536593cd5f28e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
另一個比較有用的屬性是layout_flexGrow,他被設(shè)置到FlexboxLayout的孩子view上熏挎,這個屬性有點類似于LinearLayout的layout_weight卸夕,不同的地方在于LinearLayout是根據(jù)layout_weight的值來將多余的空間分配給每個子view的高或?qū)挘鳩lexboxLayout是按照layout_flexGrow屬性的值將多余的空間轉(zhuǎn)換為在同一行的子view之間的間隔距離婆瓜。下邊的例子,將layout_flexGrow的值設(shè)為1:
<android.support.design.widget.TextInputLayout
android:layout_width="100dp"
android:layout_height="wrap_content"
app:layout_flexgrow="1">
![](http://upload-images.jianshu.io/upload_images/2758471-a8d81eaca66aedc7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
你可以從Github上得到完整的[布局文件](https://github.com/google/flexbox-layout/blob/master/app/src/main/res/layout/fragment_flex_item_edit.xml)
######與RecyclerView結(jié)合使用
FlexboxLayout的另外一個好處是他能與RecyclerView結(jié)合使用贡羔,在最新發(fā)布的alpha版本提供了新的RecyclerView布局管理器FlexboxLayoutManager他繼承自RecyclerView.LayoutManager廉白,你現(xiàn)在可以用這種更加高效利用內(nèi)存的方式在滾動容器里實現(xiàn)Flexbox功能。當(dāng)然你也可以用ScrollView結(jié)合FlexboxLayout來達到在可滾動的容器中實現(xiàn)Flexbox功能乖寒,但是當(dāng)容器中的子view數(shù)量很多的時候?qū)?dǎo)致OutOfMemoryError的發(fā)生猴蹂。事實上有許多可以用FlexboxLayout與RecyclerView結(jié)合使用的場景,比如Google 的Photos app 或新聞app楣嘁。這兩個應(yīng)用都需要顯示大量寬度不同的圖片磅轻。
下邊是一個例子珍逸,每一個顯示在RecyclerView中的圖片都有不同的寬度,我們設(shè)置flexWrap的值到wrap
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);
然后設(shè)置flexGrow的值(這樣就不用依次給每個item設(shè)置flexGrow值 )
void bindTo(Drawable drawable) {
mImageView.setImageDrawable(drawable);
ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
FlexboxLayoutManager.LayoutParams flexboxLp =
(FlexboxLayoutManager.LayoutParams) mImageView.getLayoutParams();
flexboxLp.setFlexGrow(1.0f);
}
}
效果如下:
![豎屏](http://upload-images.jianshu.io/upload_images/2758471-5ffb80a77f3878de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![橫屏](http://upload-images.jianshu.io/upload_images/2758471-d96e539cf7148f10.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看到無論是橫屏還是豎屏都能很好的適配聋溜。
本篇文章就結(jié)束了谆膳,如果您有任何問題,歡迎與我聯(lián)系撮躁。如果文中有錯誤的地方也歡迎您指證漱病,我將不勝感激。
如果您想要查看完整的例子代碼請查看:
[Playground 例子app](https://github.com/google/flexbox-layout/tree/dev_recyclerview/demo-playground) - 使用了FlexboxLayout和FlexboxLayoutManager實現(xiàn)
[Cat gallery例子app](https://github.com/google/flexbox-layout/tree/dev_recyclerview/demo-cat-gallery) - 使用FlexboxLayoutManager實現(xiàn)
本文參考自google官方文檔 https://android-developers.googleblog.com/2017/02/build-flexible-layouts-with.html