使用FlexboxLayout構建靈活的布局
去年的 Google I/O大會上我們宣布了 ConstraintLayout , 一個用簡單的視圖結構就能構建復雜布局的控件。另外,它還完全支持Android Studio的 可視化布局編輯器 。
與此同時,我們開源了 FlexboxLayout ,把css中的 Flexbox布局(Flexible Box)模塊 帶到了安卓中。這里就是一些FlexboxLayout特別有用的情形。
FlexboxLayout可以理解成一個高級版的LinearLayout,因為兩個布局都把子view按順序排列。兩者之間最大的差別在于FlexboxLayout具有換行的特性。
也就是說如果你添加了flexWrap="wrap"屬性,在當前行空間不足的情況下FlexboxLayout將把view放在下一行,就如下圖這樣:
一個布局使用不同屏幕尺寸
在這個特性的基礎上,讓我們考慮一個按序排列視圖,但是在空間發生變化的時候可以讓view移到新的一行的情況(可能因為設備因素,橫豎屏變化,或者多窗口模式下的窗口調整)。
Nexus5X 豎屏
Nexus5X 橫屏
啟用多窗口模式,分割線在左邊的的Pixel C
啟用多窗口模式,分割線在中間的的Pixel C
啟用多窗口模式,分割線在右邊的的Pixel C
如果使用傳統的布局,比如 LinearLayout或者RelativeLayout,你需要定義多個DP分類的布局(layout-600dp, layout-720dp, layout-1020dp)來處理屏幕尺寸的問題。但是上面的對話框其實是用一個FlexboxLayout構建的。
這個例子中使用到的技術就是前面提到的flexWrap="wrap",
<com .google.android.flexbox.flexboxlayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexwrap="wrap">
然后你就可以得到下面這種能換行的布局,而不是視圖從它的父布局益出。
另一個要強調的技術就是為單個子view設置layout_flexGrow 。在空間有剩余的情況下,這可以幫助改善布局的最終外觀。layout_flexGrow屬性類似于LinearLayout中的layout_weight。也就是說,FlexboxLayout將根據同一行中每個子view的layout_flexGrow的值來分配剩余的空間。
在下面的例子中,假設每個子view的layout_flexGrow屬性為1,那么剩余空間將平均分配到每個子view。
<android .support.design.widget.TextInputLayout
android:layout_width="100dp"
android:layout_height="wrap_content"
app:layout_flexgrow="1">
你可以在GitHub倉庫上找到完整的 layout xml 文件。
RecyclerView集成
FlexboxLayout的另一個好處是可以和 RecyclerView 集成。最新的 alpha 版本 中, Flexbox可以作為一個 LayoutManager(FlexboxLayoutManager)用在RecyclerView中。現在你可以以更內存友好的方式在滾動容器中使用Flexbox的功能了。
不過你仍然可以把FlexboxLayout放在ScrollView中來實現滾動。但是這樣的話如果item過多很可能會造成卡頓和內存益處的錯誤,因為FlexboxLayout并不會回收那些滾動出屏幕的view。
(如果你想了解RecyclerView的更多細節,可以看看來自ndroid UI toolkit團隊的視頻,比如 1 , 2 )
集成RecyclerView能帶來好處的真實的例子是 Google Photo app或者新聞app,兩者都具有大量的寬度各異的item。
FlexboxLayout倉庫的 demo application 中有一個這樣的例子,RecyclerView中的每個image寬度不同。但是通過把flexWrap設置為wrap,
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);
并把每個子view的flexGrow設置為一個正數,(就如你看到的,我們可以通過FlexboxLayoutManager和FlexboxLayoutManager.LayoutParam設置這個屬性,而不通過xml)
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);
}
}
你可以看到不管屏幕方向如何,布局中的每一個image都排列得都很合適。
要看看完整的FlexboxLayout,請到:
-
Playground demo app - 使用 FlexboxLayout 和 FlexboxLayoutManager.
-
Cat gallery demo app - 使用 FlexboxLayoutManager
接下來是什么?
需要其它屬性構建量為自己身定做的布局請看完整的 文檔 。我們非常歡迎來自你的反饋,如果發現什么問題或者有新的功能需求,請在 GitHub repository 上提交issue。
來自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0228/7174.html