Android ConstraintLayout约束布局的理解与使用
一、什么是約束布局(ConstraintLayout)
- ConstraintLayout 是一個使用“相對定位”靈活地確定微件的位置和大小的一個布局,在 2016 年 Google I/O 中面世,它的出現是為了解決開發中過于復雜的頁面層級嵌套過多的問題——層級過深會增加繪制界面需要的時間,影響用戶體驗,以靈活的方式定位和調整小部件。
- ConstraintLayout 是一個ViewGroup,可以在Api9以上的Android系統使用它,它的出現主要是為了解決布局嵌套過多的問題,以靈活的方式定位和調整小部件。從 Android Studio 2.3 起,官方的模板默認使用 ConstraintLayout。
- ConstraintLayout是一個Support庫,它支持向前兼容,最低可支持到API 9(android 2.3)目前app兼容性都是做到4.0以上所以ConstraintLayout的兼容性問題完全不用考慮,其本身更像是對RelativeLayout的升級,效率更高且更實用。
二、約束布局的優勢
- 搞定復雜布局
- 減少層級嵌套
- 提升頁面性能
三、如何使用約束布局
3.1 添加依賴
首先我們需要在app/build.gradle文件中添加ConstraintLayout的依賴,如下所示。
dependencies {implementation "androidx.constraintlayout:constraintlayout:2.1.1" }3.2 位置約束
3.2.1 相對定位
ConstraintLayout采用方向約束的方式對控件進行定位,至少要保證水平和垂直方向都至少有一個約束才能確定控件的位置。
約束屬性介紹:
app:layout_constraintTop_toTopOf="" 我的頂部和誰的頂部對齊
-
app:layout_constraintBottom_toBottomOf="" 我的底部和誰的底部對齊
-
app:layout_constraintLeft_toLeftOf="" 我的左邊和誰的左邊對齊
-
app:layout_constraintRight_toRightOf="" 我的右邊和誰的右邊對齊
-
app:layout_constraintStart_toStartOf="" 我的開始位置和誰的開始位置對齊
-
app:layout_constraintEnd_toEndOf="" 我的結束位置和誰的結束位置對齊
-
app:layout_constraintTop_toBottomOf="" 我的頂部位置在誰的底部位置
-
app:layout_constraintBottom_toTopOf="" 我的底部位置在誰的頂部位置
-
app:layout_constraintStart_toEndOf="" 我的開始位置在誰的結束為止
-
app:layout_constraintEnd_toStartOf="" 我的結束位置在誰的開始為止
-
app:layout_constraintLeft_toRightOf="" 我的左邊和誰的右邊對齊
-
app:layout_constraintRight_toLeftOf="" 我的右邊和誰的左邊對齊
-
app:layout_constraintBaseline_toBaselineOf="" 文本對齊(Baseline指的是文本基線)
3.2.2 角度定位
角度定位指的是可以用一個角度和一個距離來約束兩個空間的中心。
有些時候我們需要一個控件在某個控件的某個角度的位置,那么通過其他的布局其實是不太好實現的,但是ConstraintLayout為我們提供了角度位置相關的屬性。
-
app:layout_constraintCircle="" 目標控件id
-
app:layout_constraintCircleAngle="" 對于目標的角度(0-360)
-
app:layout_constraintCircleRadius="" 到目標中心的距離
3.3 邊距
3.3.1 外邊距-Margin
-
android:layout_margin="" 給每邊加外邊距
-
android:layout_marginStart="" 給起始邊加外邊距
-
android:layout_marginLeft="" 給左邊加外邊距
-
android:layout_marginTop="" 給上邊加外邊距
-
android:layout_marginEnd="" 給結束邊加外邊距
-
android:layout_marginRight="" 給右邊加外邊距
-
android:layout_marginBottom="" 給下邊加外邊距
# stat end (更強調位置) 的存在就是為了 Android中的RTL Layout 兼容,使用中效果大體一樣
3.3.2 外邊距-goneMargin
被依賴空間GONE之后生效的邊距:
- android:layout_goneMarginStart="" 當起始位置對齊的控件gone時,增加在自身起始位置的外邊距
- android:layout_goneMarginEnd="" 當結束位置對齊的控件gone時,增加在自身結束位置的外邊距
- android:layout_goneMarginLeft="" 當左對齊的控件gone時,增加在自身左邊的外邊距
- android:layout_goneMarginTop="" 當頂部對齊的控件gone時,增加在自身頂部的外邊距
- android:layout_goneMarginRight="" 當右對齊的控件gone時,增加在自身右邊的外邊距
- android:layout_goneMarginBottom="" 當底部對齊的控件gone時,增加在自身底部的外邊距
3.3.3 內邊距-padding
-
android:padding="" 給每邊加內邊距
-
android:paddingStart="" 給起始邊加內邊距
-
android:paddingLeft="" 給左邊加內邊距
-
android:paddingTop="" 給上邊加內邊距
-
android:paddingEnd="" 給結束邊加內邊距
-
android:paddingRight="" 給右邊加內邊距
-
android:paddingBottom="" 給下邊加內邊距
3.4 尺寸限制
在ConstraintLayout中提供了一些尺寸限制的屬性,可以用來限制最大、最小寬高度,這些屬性只有在給出的寬度或高度為wrap_content時才會生效,比如想給寬度設置最小或最大值,那寬度就必須設置為wrap_content,這個比較簡單就不放示例代碼了,具體的屬性如下:
-
android:minWidth="" 設置view的最小寬度
-
android:minHeight="" 設置view的最小高度
-
android:maxWidth="" 設置view的最大寬度
-
android:maxHeight="" 設置view的最大高度
設置view的大小除了傳統的wrap_content、指定尺寸、match_parent外,ConstraintLayout還可以設置為0dp(MATCH_CONSTRAINT),并且0dp的作用會根據設置的類型而產生不同的作用,進行設置類型的屬性是layout_constraintWidth_default和layout_constraintHeight_default,取值可為spread、percent、wrap。具體的屬性及示例如下:
app:layout_constraintWidth_default=“spread|percent|wrap”
app:layout_constraintHeight_default=“spread|percent|wrap”
spread(默認):占用所有的符合約束的空間
percent:按照父布局的百分比設置,percent模式的意思是自身view的尺寸是父布局尺寸的一定比例,該模式需要配合layout_constraintWidth_percent使用,但是寫了layout_constraintWidth_percent后,layout_constraintWidth_default="percent"其實就可以省略掉了。
wrap:匹配內容大小但不超過約束限制,當控件寬度(或高度)設置為wrap_content,并且設置了margin,但是內容過長會造成margin的約束不生效,使用layout_width=“0dp”,layout_constraintWidth_default="wrap"時,內容過長不會超過margin的限制值。此方式類似于layout_width=“wrap_content”(或layout_height=“wrap_content”),app:layout_constrainedWidth=“true”(或app:layout_constrainedHeight=“true”),對控件設置了強制約束。
3.5 居中與偏移
3.5.1 居中
在RelativeLayout中,把控件放在布局中間的方法是把layout_centerInParent設為true,而在ConstraintLayout中的寫法是:
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"意思是把控件的上下左右約束在布局的上下左右,這樣就能把控件放在布局的中間了。同理RelativeLayout中的水平居中layout_centerHorizontal相當于在ConstraintLayout約束控件的左右為parent的左右;RelativeLayout中的垂直居中layout_centerVertical相當于在ConstraintLayout約束控件的上下為parent的上下。
3.5.2 偏移
- 使用邊距
- layout_constraintHorizontal_bias 水平偏移 (0-1 ,0,則在左對齊控件的最右側,假如賦值為1,則在右對齊控件的最左側,假如賦值為0.5,則水平居中,假如賦值為0.3,則更傾向于左側)
- layout_constraintVertical_bias 垂直偏移 (類似,同上)
3.6 鏈(chain)
如果兩個或以上控件通過下圖的方式約束在一起,就可以認為是他們是一條鏈。
一條鏈的第一個控件是這條鏈的鏈頭,我們可以在鏈頭中設置 layout_constraintHorizontal_chainStyle(或layout_constraintVertical_chainStyle)來改變整條鏈的樣式。chains提供了3種樣式,分別是:
-
spread —— 展開元素 (默認),如圖:
-
spread_inside —— 展開元素,但鏈的兩端貼近parent,如圖:
-
packed —— 鏈的元素將被打包在一起,如圖:
-
與權重結合為權重鏈,約束布局設置某方向權重,需要將其layout_width=“0dp”(或layout_height=“0dp”),設置橫向權重layout_constraintHorizontal_weight(constraintVertical為縱向)來創建一個權重鏈,如圖(A控件layout_constraintHorizontal_weight=“1”,B、C控件layout_constraintHorizontal_weight=“2”):
-
packed chain+bias——打包后按設置偏移
3.7 Barrier(屏障)
- app:barrierDirection為屏障所在的位置,可設置的值有:bottom、end、left、right、start、top
- app:constraint_referenced_ids為屏障引用的控件,可設置多個(用“,”隔開)
- app:barrierAllowsGoneWidgets=“true/false” 定義在引用形成Barrier的視圖gone時是否仍然有效
解釋:在TextView1,TextView2的右側設置了屏障,TextView3左邊對齊屏障的右邊。不管1、2的寬度發生如何變化,屏障永遠在他們的右邊,3也永遠在屏障的右邊(也就在1,2的右邊),如圖:
3.8 Optimizer
當我們使用 MATCH_CONSTRAINT 時,ConstraintLayout 將對控件進行 2 次測量,ConstraintLayout通過設置 layout_optimizationLevel 進行優化,可設置的值有:
- none:無優化
- standard:僅優化直接約束和屏障約束(默認)
- direct:優化直接約束
- barrier:優化屏障約束
- groups: 優化Group約束
- chains:優化鏈約束
- dimensions:優化尺寸測量
3.9 Group
Group可以把多個控件歸為一組,可以方便控制一組控件顯示或隱藏。
eg:
效果如圖:
將Group設置gone時,效果如圖:
主要是通過 constraint_referenced_ids 這個屬性來實現,然后控制 Group 顯示或隱藏就能同時控制加入進去的子控件。Group 使用注意事項:
- Group優先于View,下層Group優先于上層。
- Group只可以引用當前ConstraintLayout下的View,子Layout 下的View不可以。
- app:constraint_referenced_ids里直接寫的是id的字符串,初始化后會通過getIdentifier來反射查找叫該名字的id。所以如果你的項目用了類似AndResGuard的混淆id名字的功能,切記不要混淆app:constraint_referenced_ids里的id,否則在release版本就會因找不到該id而失效?;蛘咭部梢酝ㄟ^代碼setReferencedIds來設置id。
3.10 Placeholder
Placeholder指的是占位符,在Placeholder中可通過屬性 app: content = “id” 控制對應的控 件繪制到自己的位置上,或使用setContent()設置另一個控件的id,使這個控件移動到占位符的位置。
eg:
若未設置app:content="@+id/tv_right3",效果如圖:
3.11 Guideline
輔助線,幫助定位控件,并不會顯示在界面上。
Guildline的主要屬性:android:orientation 垂直vertical,水平horizontal。
- layout_constraintGuide_begin 開始位置(水平方向,距離頂部。垂直距離左側)
- layout_constraintGuide_end 結束位置(水平方向,距離頂部。垂直距離左側)
- layout_constraintGuide_percent 距離的百分比(水平方向,距離頂部。垂直距離左側)
eg:
效果如圖:
3.12 額外的非必要屬性
下面幾個屬性是 UI 編輯器所使用的,用了輔助拖拽布局的,在實際使用過程中,可以不用關心這些屬性。
● layout_optimizationLevel
● layout_editor_absoluteX
● layout_editor_absoluteY
● layout_constraintBaseline_creator
● layout_constraintTop_creator
● layout_constraintRight_creator
● layout_constraintLeft_creator
● layout_constraintBottom_creator
四、代碼中設置約束:
通過ConstraintSet,允許在代碼中進行約束設置,進行布局變換。(API 19及以上支持trasmition動畫)
創建ConstraintSet對象的幾種方式:
手動:
c = new ConstraintSet(); c.connect(....);通過一個R.layout.xxx對象
c.clone(context, R.layout.layout1);通過一個ConstraintLayout對象
c.clone(clayout);布局變化開啟平滑動畫的方式:
TransitionManager.beginDelayedTransition(constraintLayout);其中參數constraintLayout表示動畫作用的約束布局對象。
總結
以上是生活随笔為你收集整理的Android ConstraintLayout约束布局的理解与使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kotlin与Java的几种单例模式
- 下一篇: android sdk投屏,海豚星空扫码