目錄:
1、為什麼要用ConstraintLayout?
2、ConstraintLayout有哪些缺點?
3、怎麼使用ConstraintLayout。
1、為什麼要用ConstraintLayout?
- 任何複雜的佈局只需一層(除非有巢狀的事件響應需求):
繪製過程中的每個階段都需要對檢視樹執行一次自頂向下的遍歷操作。因此,檢視層次結構中嵌入(或巢狀)的檢視越多,裝置繪製檢視所需的時間和計算功耗也就越多。通過在 Android 應用佈局中保持扁平的層次結構,您可以為應用建立響應快速而靈敏的介面。
- 效能更出色
ConstraintLayout 在測量/佈局階段的效能比 RelativeLayout大約高 40%。 詳情參閱:解析ConstraintLayout的效能優勢
- LinearLayout和RecyclerView的佈局能做到的ConstraintLayout都能做到,它們做不到的也能做到(這一點後面詳解)。
2、它有哪些缺點?
- xml很囉嗦
主要體現在兩方面: 1、它需要通過詳盡的屬性來確定自身位置,因為以前用LL或RL的寫法,有些屬性在父容器寫一次就夠,子容器就無需再寫一次,但這個是每個容器都是獨立的,需要根據周圍的控制元件確定自身的位置。所以這就引出了第二個囉嗦。 2、每個View都要有與之對應的id。
- 沒有gravity屬性,這裡後面會講到一個“拉力”的概念,這裡先簡單說一下,怎麼實現gravity=center這樣的效果呢?需要把每個邊都與父容器的邊對應上(需設定4個屬性),因為四個邊都要拉扯以將控制元件拉到中間。
3、怎麼使用?
1、引入資源
compile 'com.android.support.constraint:constraint-layout:1.0.2'
複製程式碼
2、熟悉它的屬性,主要有幾部分:
part1:類似於RelativeLayout的部分:
根據其他控制元件給自身定位:
layout_toRightOf="A"——>layout_constraintLeft_toRightOf="A"
根據父容器給自身定位:
layout_alignParentRight=true——>layout_constraintRight_toRightOf=parent
類似的還有:
layout_constraintRight_toLeftOf layout_constraintRight_toRightOf layout_constraintTop_toTopOf layout_constraintTop_toBottomOf layout_constraintBottom_toTopOf layout_constraintBottom_toBottomOf //根據某控制元件的基線對齊 layout_constraintBaseline_toBaselineOf
part2:類似LinearLayout的weight效果
官方有張圖,如[圖1]所示,通常來說,LinearLayout的weight只能實現第四行的效果,但ConstraintLayout可以實現下圖全部。
想實現類似LL(LinearLayout)的weight的效果,重點看每個TextView的最下三行以及每個TextView的layout_width都是0,以下佈局可以實現三個TextView。<TextView
android:id="@+id/tab1"
android:layout_width="0dp"
android:layout_height="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tab2" />
<TextView
android:id="@+id/tab2"
android:layout_width="0dp"
android:layout_height="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/tab1"
app:layout_constraintRight_toLeftOf="@+id/tab3" />
<TextView
android:id="@+id/tab3"
android:layout_width="0dp"
android:layout_height="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/tab2"
app:layout_constraintRight_toRightOf="parent" />
複製程式碼
如果想實現2:1:1等分的效果,就如[圖1]的第四行,需要給每個TextView分別新增如下屬性,並挨個設定值為2,1,1即可:
app:layout_constraintHorizontal_weight
複製程式碼
part3:以下是LinearLayout和RelativeLayout都做不到的,或者說是[要花很大的代價才能實現]這種表達是不是更準確點?
1、先說一下【鏈(Chains)】的概念:
ConstraintLayout中的控制元件想要定位準確,A控制元件是要依賴於父容器左側和B,然後B控制元件依賴於A和B,C依賴於B以及父容器的右側,就如圖2所示:
這個鏈代表了某種約束和拉力,上圖A,B,C之間存有間隙,(ps:如果要無間隙等分的話,需設定layout_width=0dp),圖2每個控制元件拉力都是一樣的,如果想實現[圖1]的其他效果,實際上都是根據拉力大小變化來實現的,B拉力大一點,那A和C都更靠近B一點點,類似這樣的道理。
這裡要引出一個屬性:
layout_constraintHorizontal_chainStyle
複製程式碼
該屬性有三個值:spread(鋪開),spread_inside(裡面鋪開), packed(擁擠),效果依次對應圖1的:第1行,第2行,第4行。 預設是spread。(ps:以上效果layout_width是固定值或wrap_content,如果是0的話就會類似第3行那樣)
2、用bias(偏斜)實現[圖1]第5行的效果
簡而言之就是調整C控制元件兩邊的拉力即可,對應的屬性是:
layout_constraintHorizontal_bias //水平線的拉力
layout_constraintVertical_bias //垂直線的拉力
複製程式碼
該屬性的值是0~1,預設是0.5,通過調整水平線的拉力即可達到第5行的效果了。
3、控制元件的寬高比
以前如果想要實現一個Banner寬高比是2:1這樣的,很麻煩,因為每個機型解析度有大有小,除非程式碼執行才能知道螢幕寬度是多少,才能動態得到螢幕寬度,在xml中根本無法實現。 但ConstraintLayout提供了一個屬性就能實現:
app:layout_constraintDimensionRatio="W,2:1"
或
app:layout_constraintDimensionRatio="H,1:2"
複製程式碼
注意:寬高需要設定0dp才能有效果!
part4:關於Guideline(輔助線)
這個是為了方便ConstraintLayout佈局,如果用過CAD的朋友就應該知道輔助線,用來輔助畫圖很方便,而且儲存檔案的時候該線是不會顯示到圖片上的,同理,這個也只是在寫xml的時候輔助用的,應用真正執行的時候是看不到的。
因為是一條線嘛,自然要區分水平還是垂直的,所以就有一個屬性:
android:orientation
複製程式碼
取值為”vertical”和”horizontal”,跟RecyclerView一樣。
它還有一些屬性用來給輔助線找準位置,然後給輔助線命名個id,其他控制元件只要基於該先找到自己的位置就好啦~
layout_constraintGuide_begin
layout_constraintGuide_end
layout_constraintGuide_percent
複製程式碼
它有兩種方式來找到自己的位置,一個是絕對值,也就是begin&end(取值為dp),一個是百分比percent(取值為0~1)。
當orientation為vertical的時候,begin對應距離頂部,end對應距離底部。
當orientation為horizontal的時候,begin對應距離左邊,end對應距離右邊。
真正使用的時候,就把Guideline當作一個View來用好了,Android Studio也會有預覽給你看的,記得要給它命名啊,不然其他控制元件怎麼基於它定位呢,對吧?
更多請參閱:
1、鴻洋:ConstraintLayout 完全解析 快來優化你的佈局吧
2、郭霖:Android新特性介紹,ConstraintLayout完全解析
3、Google官方文件——ConstraintLayout
4、Google官方文件——Guideline
5、解析ConstraintLayout的效能優勢