使用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團隊的視頻,比如 12

集成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,請到:

接下來是什么?

需要其它屬性構建量為自己身定做的布局請看完整的 文檔 。我們非常歡迎來自你的反饋,如果發現什么問題或者有新的功能需求,請在  GitHub repository 上提交issue。

 

來自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0228/7174.html

 

 本文由用戶 WCUMarisol 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!