這篇文章主要參考了官方文件和阮老師的Flex 佈局教程:語法篇
簡介
最近Google開源了一個叫flex-box的庫,它的思路是參照的CSS的Flex佈局設計的,所以屬性基本都是和CSS上的Flex佈局保持一致,但因為是兩個不同的平臺,所以減少了幾個不適用於Android的屬性,新增了幾個屬性,具體我們下面會說到。
關於CSS的Flex佈局
在瞭解Google開源的flex-box,我覺得有必要先了解下CSS的Flex佈局,這有助於我們理解那些屬性定義。關於這方面的知識,可以閱讀這篇部落格。下面我們只是簡要的瞭解下,具體屬性我們放到講解Google的flex-box中去說明。
//這段文字說明,來源於上面說到的部落格
採用Flex佈局的元素,稱為Flex容器(flex container),簡稱"容器"。它的所有子元素自動成為容器成員,稱為Flex專案(flex item),簡稱"專案"。
容器預設存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end。
專案預設沿主軸排列。單個專案佔據的主軸空間叫做main size,佔據的交叉軸空間叫做cross size。複製程式碼
關於Google的flexbox-layout
注意:以下文中用到的flexbox-layout指的是Google開源的庫,Flex指的是CSS中的Flex佈局。
首先我們需要知道的是,flexbox-layout的基本概念和Flex是一樣的,最外面的這層佈局稱為容器,在flexbox-layout指的是com.google.android.flexbox.FlexboxLayout
,裡面的子元素稱為專案。容器預設存在兩條軸,其中水平(這裡是就上面的概念圖而言,因為主軸的方向是可以指定的)的這條軸稱為主軸(個人理解,可以存在多條,具體原因後面講),垂直的這條稱為交叉軸。其他屬性比如start
,end
等等也是一樣的,具體可以看上面的基本概念圖。
下面我們著重講下flexbox-layout支援的屬性,因為它既支援容器屬性,也支援專案屬性,所以我們分成兩個篇幅來說明。
注意:以下屬性設定的具體效果請參照說明文件和Demo,github地址
容器屬性
flexDirection
這個屬性用於確定主軸方向,可選的值有:
- row 水平方向,起點在左邊。預設值
- row_revers 水平方向,起點在右邊。
- column 垂直方向,起點在上邊。
- column_reverse 垂直方向,起點在下邊。
flexWrap
這個屬性控制容器是單行還是自動換行,以及主軸的方向,可選的值有:
- nowrap 單行。預設值
- wrap 自動換行,第一行在上方
- wrap-reverse 自動換行,第一行在下方
關於
wrap
和wrap-reverse
的區別:justifyContent
這個屬性控制專案在主軸上的對齊方式,可選的值有:
注意:具體的對齊方式與主軸的方向有關,下面的說明是基於預設值
- flex_start 左對齊,預設值
- flex_end 右對齊
- center 居中對齊
- space_between 兩端對齊,專案之間的間隔相等
- space_around 每個專案兩側的間隔相等。所以,專案之間的間隔比專案與邊框的間隔大一倍
關於
space_between
和space_around
的樣式如下:alignItems
這個屬性定義專案在交叉軸上的對齊方式,可選的值有:
注意:具體的對齊方式與主軸的方向有關
- stretch 佔滿整個容器高度,預設值
- flex_start 交叉軸的起點對齊
- flex_end 交叉軸的終點對齊
- center 居中對齊
- baseline 專案的第一行文字的基線對齊
關於
stretch
和baseline
的樣式如下:alignContent
這個屬性控制容器的多條主軸的對齊方式,這也是我們前面提到的主軸可以有多條,當
flexWrap:wrap|wrapreverse
。可選的值有:注意:只有一條主軸,該屬性不起作用
- stretch 佔滿整個交叉軸,預設值
- flex_start 與交叉軸的起點對齊
- flex_end 與交叉軸的終點對齊
- center 與交叉軸的中心對齊
- space_between 與交叉軸兩端對齊,軸線之間的間隔平均分佈
- space_around 每根軸線兩側的間隔都相等。所以,軸線之間的間隔比軸線與邊框的間隔大一倍
這裡需要注意區別下和
alignItems
的區別,alignContent
是多條主軸基於交叉軸的對齊方式,而後者是專案基於交叉軸的對齊方式,一個是軸,一個是專案。showDividerHorizontal
dividerDrawableHorizontal
showDividerVertical
dividerDrawableVertical
showDivider
dividerDrawable
這幾個屬性都是跟分隔符有關,具體用法可以看文件。
專案屬性
layout_order(integer)
這個屬性可以改變專案的排列順序,預設值為
1
。layout_flexGrow(float)
這個屬性定義專案基於當前行的放大比例,預設值為
0
。這個屬性類似LinearLayout
中的layout_weight
屬性,如果當前行只有一個專案的layout_flexGrow
為正值,則該專案將佔滿當前行剩餘的空間,下面的效果是三個相同大小的專案,其中一個layout_flexGrow
為正值的效果:如果存在多個
layout_flexGrow
為正值的情況,則這幾個專案則會按設定的值為比例佔用當前行剩餘的空間,下面的效果是三個相同大小的專案,其中兩個專案設定layout_flexGrow:1
的效果:layout_flexShrink (float)
這個屬性定義了專案的縮小比例,預設為
1
,即如果當前行空間不足,該專案縮小的方式。如果所有專案的
layout_flexShrink
屬性都為1,當空間不足時,都將等比例縮小。如果一個專案的layout_flexShrink
屬性為0,其他專案都為1,則空間不足時,前者不縮小。個人理解,注意:要設定
flexWrap:nowrap
為單行layout_alignSelf
該屬性允許單個專案與其他專案不一樣的基於交叉軸的對齊方式。預設值為
auto
,即按照容器的alignItems
屬性,設定其他值,則會覆蓋容器的值,可選的值:- auto 預設值
- flex_start
- flex_end
- center
- baseline
- stretch
layout_flexBasisPercent (fraction)
這個屬性設定專案長度相對於容器的百分比,如果設定了這個值,則從
layout_width
或layout_height
指定的長度會被覆蓋,需要注意的是,這個屬性只在容器長度確定的情況下有效,即MeasureSpec.EXACTLY
。預設值為-1
,表示不設定。layout_minWidth / layout_minHeight (dimension)
layout_maxWidth / layout_maxHeight (dimension)
這些屬性設定對專案的最大最小限制
layout_wrapBefore (boolean)
這個屬性預設值為
false
,如果設定為true
,則該專案將強制成為當前行的第一個專案,會忽略flex_wrap:nowrap
設定。
應用例項
底部按鈕
流式佈局
TODO