1.介紹
限制布局
ConstraintLayout
本身就是一個ViewGroup,它用來解決布局嵌套過多的問題(嵌套越多,繪制消耗的時間越長),以靈活的方式定位/調整小部件(API 9以上均可使用),相比RelativeLayout更靈活,性能更加的出色,更好的适配螢幕大小不同的機型。Android Studio 2.3開始預設建立Activity是都是使用它。
2.使用
使用它也非常的簡單,高版本的AS通常都會自動的添加它的依賴,如果未添加依賴在app/build.gradle中添加相應的依賴即可。
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
2.1 相對定位
即一個元件相對于另一個元件的限制,非常的好了解(與RelativeLayout非常的類似)。
例:要實作B在A的右側:
按鈕A在按鈕B的右側,也可以了解為按鈕B的左側位于按鈕A的右側;其他的方位都一樣。我們在代碼中的表示如下:
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintLeft_toRightOf="@id/btn1" />
其中最關鍵的屬性為
app:layout_constraintLeft_toRightOf="@id/btn1"
,代表按鈕B的左側位于按鈕A的右側
其中常用的屬性還有:
// 值可以為parent,意思就是A的左側位于父布局的左側(top_top|bottom_bottom等一樣)
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf 在兩個控件高度不一樣時,可以保證文字對齊
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
引用官方的一張圖來說明這些屬性:
比較特殊的有
layout_constraintBaseline_toBaselineOf
,如圖所示,兩個Button的高度不一緻,但是又希望他們文本對齊,這個時候就可以使用
layout_constraintBaseline_toBaselineOf
保證文字相對齊:
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="Button3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="Button4"
app:layout_constraintBaseline_toBaselineOf="@id/btn3"
app:layout_constraintLeft_toRightOf="@id/btn3" />
2.2 角度定位
角度定位指的是利用角度以及距離決定某些控件中心點的坐标。
三個屬性為:
-
指定相對于哪個控件app:layout_constraintCircle="@id/btn3"
-
角度app:layout_constraintCircleAngle="160"
-
中心點的距離app:layout_constraintCircleRadius="150dp"
其中的關系如下圖所示:
例子:按鈕5在按鈕3的160度方向距離為150dp
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="Button3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button5"
app:layout_constraintCircle="@id/btn3"
app:layout_constraintCircleAngle="160"
app:layout_constraintCircleRadius="150dp" />
效果圖:
2.3 Margin
使用Margin時,用法與其他布局的一緻,前提條件是:必須指定了相對應的限制,Margin值隻能大于等于0。
唯一特殊的地方:在對應限制的控件隐藏時,相當于一個點,可使用如下Margin來設定隐藏後的Margin值
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
2.4 居中偏移
如何實作居中:即利用相對定位中的4個屬性即可
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
偏移(Bias): 使用
app:layout_constraintHorizontal_bias="0.3"
屬性即可(值在0-1之間)
1.
layout_constraintHorizontal_bias 水準偏移
2.
layout_constraintVertical_bias 垂直偏移
上下居中,水準偏移為0.3
2.5 尺寸限制
提供了一下四種方式:
- 固定值
-
wrap_content,自己進行計算
當控件的高度或寬度為wrap_content時,可以使用下列屬性來控制最大、最小的高度或寬度:
android:minWidth 最小的寬度
android:minHeight 最小的高度
android:maxWidth 最大的寬度
android:maxHeight 最大的高度
- 使用0dp 官方不推薦在ConstraintLayout中使用match_parent,可設定
寬高比:當寬或高至少一個被設定為0dp時,可通過屬性layout_constraintDimensionRatio設定寬高比還可以在值的前面加上W或者H0dp(MATCH_CONSTRAINT)配合代替match_parent
app:layout_constraintDimensionRatio="W,2:1" 寬高比2:1
app:layout_constraintDimensionRatio="H,2:1" 高寬比2:1
<Button
android:id="@+id/btn6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button6"
android:layout_marginStart="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn5" />
<!-- 通過layout_constraintDimensionRatio 設定寬高比 -->
<Button
android:id="@+id/btn7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button7"
app:layout_constraintDimensionRatio="W,2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn6" />
效果圖:
2.6 鍊
如果兩個或以上控件通過下圖的方式限制在一起,就可以認為是他們是一條鍊(圖為橫向的鍊,縱向同理)。
一條鍊的第一個控件是這條鍊的鍊頭,我們可以在鍊頭中設定鍊的Style,相關的Style有:
app:layout_constraintHorizontal_chainStyle="spread|spread_inside|packed"
app:layout_constraintVertical_chainStyle="spread|spread_inside|packed"
- CHAIN_SPREAD : 預設模式(展開元素)
- CHAIN_SPREAD_INSIDE :展開元素,兩端靠近parent邊緣
- CHAIN_PACKED :控件被整合在一起
- Weighted Chain: 權重鍊,當寬度或者高度被設定成0dp時,layout_constraintHorizontal_weight 和 layout_constraintVertical_weight控制所占比例
注意:在鍊中的元素上使用邊距時,邊距是相加的。A Margin right 10,B Margin left 5,total 15
Style的形式使用下圖表示:
使用案例:
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn2" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintLeft_toRightOf="@id/btn1"
app:layout_constraintRight_toLeftOf="@id/btn3" />
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
app:layout_constraintLeft_toRightOf="@id/btn2"
app:layout_constraintRight_toRightOf="parent" />
packed模式:
spread模式:
spread_inside模式:
Weighted Chain模式,必須存在一個0dp:
3.輔助工具的使用
3.1 Optimizer
當我們使用 MATCH_CONSTRAINT 時,ConstraintLayout 将對控件進行 2 次測量,ConstraintLayout在1.1中可以通過設定 layout_optimizationLevel 進行優化,可設定的值有:
- none 無優化
- Standard 僅優化直接限制/屏障限制(預設)
- Direct 優化直接限制
- Barrier 優化屏障限制
- Chain 優化鍊限制
- Dimensions 優化尺寸測量
3.2 Barrier(屏障)
詳參:https://developer.android.google.cn/reference/android/support/constraint/Barrier
A與B的寬度未知,現在讓C限制在A或者B的右側都不對;這種情況可用Barrier解決,它相當于在AB的一側與C之間加了一個屏障。
使用Barrier後如下圖(A B都在屏障内):
主要的屬性:
app:barrierDirection="end|top|bottom|start|left|right"
等設定屏障的位置
app:constraint_referenced_ids=””
設定屏障引用的控件,多個值時用’,’隔開
例子:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:text="Button4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="6dp"
android:text="Button5 Button5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button1" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="button1,button2" />
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="10dp"
android:text="為了看到整體的效果,可以切換語言,
此時你會看到Barrier會自動位于較寬的那個textView後面,
也就間接讓 textView3 也位于了正确的位置"
app:layout_constraintLeft_toRightOf="@id/barrier"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
效果:
最終在C中引用Barrier的限制即可,使用後不管A或者B的寬度如何變化,C始終都位于屏障的右側
3.3 Group
詳參:https://developer.android.google.cn/reference/android/support/constraint/Group
主要作用:把控件歸類為一組,更加便捷的管理顯示與否等
控件隐藏前:
使用Group,并且添加相關的依賴:
app:constraint_referenced_ids="btn2,btn3"關聯關系
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintLeft_toRightOf="@id/btn1" />
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
app:layout_constraintLeft_toRightOf="@id/btn2" />
<android.support.constraint.Group
app:constraint_referenced_ids="btn2,btn3"
android:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
控件隐藏後:
3.4 Placeholder
詳參:https://developer.android.google.cn/reference/android/support/constraint/Placeholder
占位符,可使用setContent設定另一個控件的id,使這個控件移動到占位符的位置.
通過
app:content="@+id/btn1"
屬性設定要移動的View
案例:設定Button在右上角,設定Placeholder在左下角,設定content後,Button移動到Placeholder的位置(左下角)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.constraint.Placeholder
android:id="@+id/ph"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content="@+id/btn1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
</android.support.constraint.ConstraintLayout>
效果:
3.5 Guideline
詳參:https://developer.android.google.cn/reference/android/support/constraint/Guideline
布局輔助線,預覽的時候幫助我們完成布局(不顯示在界面上)
主要屬性:
android:orientation="horizontal|vertical"
app:layout_constraintGuide_end = “50dp”
結束位置
app:layout_constraintGuide_begin = “50dp”
開始位置
app:layout_constraintGuide_percent="0.6"
距離頂部的百分比(orientation = horizontal時則為距離左邊)
例子:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<android.support.constraint.Guideline
android:id="@+id/line1"
android:orientation="horizontal"
app:layout_constraintGuide_begin="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.constraint.Guideline
android:id="@+id/line2"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.6"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.constraint.Guideline
android:id="@+id/line3"
android:orientation="horizontal"
app:layout_constraintGuide_end="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
效果:
ConstraintLayout 的使用就簡單介紹到這裡
參考文章