Android之FlexboxLayout彈性佈局的介紹
Google最近開源了一個和CSS3中FlexBox佈局功能類似的flexbox-layout,專案地址:google/flexbox-layout ,Google將其引入以提高複雜佈局的能力。
FlexBoxLayout可以理解成一種更高階的LinearLayout,不過比LinearLayout更加強大和靈活。如果我們使用LinearLayout佈局的話,那麼不同的解析度,也許我們要重新調整佈局,勢必會需要跟多的佈局檔案放在不同的資源目錄。而使用FlexBoxLayout來佈局的話,可以簡單、完整、響應式的實現各種頁面佈局。
具體使用方式在專案地址的介紹文件有講解,只需要新增一下依賴:
compile 'com.google.android:flexbox:0.2.7'
(1)下面介紹Flexbox的佈局和相關名稱所代表的意思
上圖是官方給出的示例圖,其中的概念:
1、flex container:父容器,用來包含子元素,對應於FlexboxLayout類;
2、flex item:子元素,父容器直接包裹的元素;
3、main axis:主軸,子元素通過主軸來排列,如上圖是從左往右;
4、corss axis:副軸,垂直於主軸的第二個軸,從上往右;
5、main start和main end:父容器中主軸開始和結束的邊界,子元素從main start往main end的方向排列(如果主軸是水平,起點在左端,main start,main end 用來控制子元素從左向右排列);
(2)FlexboxLayout所支援的屬性
Container的屬性
1、flexDirection: 屬性決定主軸(和副軸,垂直於主軸的方向(即專案中子元素的排列方向);
有以下四個值:
row (default):主軸為水平方向,起點在左端;
row_reverse:主軸為水平方向,起點在右端;
column:主軸為垂直方向,起點在上沿;
column_reverse:主軸為垂直方向,起點在下沿;
2、flexWrap:預設情況下FlexboxLayout跟LinearLayout一樣,都不帶換行排列的,但是flexWrap屬性可以支援換行排列。
有以下三個值:
nowrap (default):不換行;
wrap:換行,如下圖所示;
wrap_reverse:副軸方向置反,上圖倒置一下,具體可以自己執行試驗一下;
3、justifyContent:定義了子項在主軸上的對齊方式,控制子項沿主軸對齊。
有以下五個值:
flex_start(預設值):左對齊;
flex_end:右對齊;
center:居中;
space_between:兩端對齊,專案之間的間隔都相等;
space_around:每個專案兩側的間隔相等。所以,專案之間的間隔比專案與邊框的間隔大一倍。
4、alignItems:屬性定義子項在副軸軸上如何對齊,控制子項沿副軸對齊(單行起作用)。
有以下五個值:
flex_start:交叉軸的起點對齊;
flex_end:交叉軸的終點對齊;
center:交叉軸的中點對齊;
baseline: 專案的第一行文字的基線對齊;
stretch(預設值):如果專案未設定高度或設為auto,將佔滿整個容器的高度;
5、alignContent:屬性定義多根軸線的對齊方式。如果專案只有一根軸線,該屬性不起作用。
有以下六個值:
flex_start:與交叉軸的起點對齊;
flex_end:與交叉軸的終點對齊;
center:與交叉軸的中點對齊;
space_between:與交叉軸兩端對齊,軸線之間的間隔平均分佈;
space_around:每根軸線兩側的間隔都相等。所以,軸線之間的間隔比軸線與邊框的間隔大一倍;
stretch(預設值):軸線佔滿整個交叉軸;
6、showDividerHorizontal / showDividerVertical:控制顯示水平 / 垂直方向的分割線,值為none、beginning、middle和end其中的一個或者多個;
7、dividerDrawableHorizontal / dividerDrawableVertical:設定Flex 軸線之間水平方向 / 垂直方向的分割線;
8、showDivider:控制顯示水平和垂直方向的分割線,值為none | beginning | middle | end其中的一個或者多個。
9、dividerDrawable:設定水平和垂直方向的分割線,但是注意,如果同時和其他屬性使用,比如為 Flex 軸、子元素設定了justifyContent=”space_around” 、alignContent=”space_between” 等等。可能會看到意料不到的空間,因此應該避免和這些值同時使用。
子元素的屬性
FlexboxLayout除了上述屬性外,還支援如下子元素屬性:
1、layout_order: 控制子元素佈局的順序,預設值為1,這種情況下子元素的排列方式按照文件流的順序依次排序,而order屬性可以控制排列的順序,負值在前,正值在後,按照從小到大的順序依次排列。
2、layout_flexGrow:類似於LinearLayout中的weight屬性一樣;
如果所有子項的layout_flexGrow屬性都為1,則它們將等分剩餘空間(如果有的話),即每個子項佔有三分子一。如果一個專案的 layout_flexGrow 屬性為2,其他專案都為1,則前者佔據的剩餘空間將比其他項多一倍;
3、layout_flexShrink:定義了子項的縮小比例,預設為1,即如果空間不足,該子項將縮小,如果為0,則不變化;
如果所有子項的 layout_flexShrink 屬性都為1,當空間不足時,都將等比例縮小。如果一個專案的flex-shrink屬性為0,其他專案都為1,則空間不足時,前者不縮小;
4、layout_alignSelf:允許單個元素有與其它子項不一樣的對齊方式,可覆蓋alignItems屬性,預設值為auto,表示繼承父元素的alignItems屬性,如果沒有父元素,則等同於stretch;
auto (default):繼承父元素的alignItems;
flex_start:以下五項和alignItems相同;
flex_end
center
baseline
stretch
5、layout_flexBasisPercent:只能為百分比的值,表示設定子項的長度為它父容器長度的百分比,如果設定了這個值,那麼通過這個屬性計算的值將會覆蓋layout_width或者layout_height的值,但是,只有父容器的MeasureSpec的Mode是MeasureSpec.EXACTLY的模式時才有效,預設值是-1;
6、layout_minWidth / layout_minHeight (dimension):強制限制 FlexboxLayout的子元素(寬或高)不會小於最小值,不管layout_flexShrink這個屬性的值為多少,子元素不會被縮小到小於設定的這個最小值;
7、layout_maxWidth / layout_maxHeight (dimension):這個和上面的剛好相反,強制限制FlexboxLayout子元素不會大於這個最大值, 不管layout_flexGrow的值為多少,子元素不會被放大到超過這個最大值;
8、layout_wrapBefore:屬性控制強制換行,預設值為false,如果將一個子元素的這個屬性設定為true,那麼這個子元素將會成為一行的第一個元素。這個屬性將忽略flex_wrap 設定的 noWrap值;
(3)與傳統CSS彈性佈局不同之處
1、沒有flex-flow屬性 :因為沒必要;
2、沒有flex屬性:同樣沒必要;
3、layout_flexBasisPercent 替代了flexBasis。如果子元素寬高確定了,可以指定具體值或百分比,如果是包裹內容,那隻能是百分比;
4、不能確定min-width和min-height:因為谷歌還沒實現;
(4)總結
FlexboxLayout是一個與CSS Flexbox有類似功能的強大布局,具有換行特性,使用起來特別方便,但是,FlexboxLayout是沒有考慮View回收的,因此,它只使用於只有少量子Item的場景,如果向其中新增大量Item 是灰導致記憶體溢位的。所幸,最新的版本添加了與RecyclerView的整合,這就可以在有大量子Item的場景下使用了,只是最新的版本還是alpha版,還沒有出穩定的版本,相信不久後就能使用穩定的版本了。另外,FlexboxLayout的這些屬性的含義可能不好理解 ,建議大家去寫個demo試一下每個屬性的每個值看看是什麼效果,這樣就能很好的理解每個屬性了。筆者就是自己模仿著官方給的,自己寫了一遍試一試各個屬性的效果;
小demo:https://github.com/henryneu/MyFlexboxLayout
參考: