優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 極大程度減少布局層級(jí)
- 可以實(shí)現(xiàn)一些其他布局管理器不能實(shí)現(xiàn)的樣式
缺點(diǎn)
- 每個(gè)被參考的控件都需要設(shè)置id
以下所有描述都是針對(duì)ConstraintLayout下子控件的,通用的屬性在此不再敘述沟娱,只針對(duì)ConstraintLayout獨(dú)有屬性進(jìn)行探討酣溃。
基本用法
一箫爷、定位
1. 相對(duì)定位
- 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:文字Baseline對(duì)齊
- layout_constraintStart_toEndOf
- layout_constraintStart_toStartOf
- layout_constraintEnd_toStartOf
- layout_constraintEnd_toEndOf
以下代碼表示tv2頂部與tv1頂部對(duì)齊
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
...
/>
<TextView
android:id="@+id/tv2"
...
app:layout_constraintTop_toTopOf="@id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. 圓形定位
layout_constraintCircle : 參考控件的id
layout_constraintCircleRadius : 本控件與參考控件中心點(diǎn)間距
-
layout_constraintCircleAngle : 角度0~360
以下代碼表示Textview中心位于id為targetId控件的中心距離30dp角度為30度的位置
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
...
app:layout_constraintCircle="@id/targetId"
app:layout_constraintCircleAngle="30"
app:layout_constraintCircleRadius="30dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
3. 百分比定位(bias)
- layout_constraintHorizontal_bias
- layout_constraintVertical_bias
取值范圍0~1灸眼,默認(rèn)值0.5
以下代碼表示Textview中心位置位于ConstraintLayout寬度的30%處
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
...
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
4. 居中對(duì)齊
所有居中對(duì)其需要設(shè)置對(duì)應(yīng)方向尺寸大小為wrap_content或固定值
- 水平居中
以下代碼表示Textview相對(duì)于ConstraintLayout水平居中
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
...
android:layout_width="60dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
注意:
- 這里的left和right換成start和end也是可以的
- 這里的parent換成參考控件的id也是可以的
- 垂直居中
以下代碼表示Textview相對(duì)于ConstraintLayout垂直居中
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
...
android:layout_height="60dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
注意:這里的parent換成參考控件的id也是可以的
5. 單邊對(duì)齊
以下代碼表示tv2和tv3與tv1頂部對(duì)齊
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
...
/>
<TextView
android:id="@+id/tv2"
...
app:layout_constraintTop_toTopOf="@id/tv1" />
<TextView
android:id="@+id/tv3"
...
app:layout_constraintTop_toTopOf="@id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>
注意:這里寫法比較多樣南窗,以上展示的都是以統(tǒng)一的單個(gè)控件為參考點(diǎn)耙厚,也可以以相關(guān)控件為參考點(diǎn)渠缕,比如這里的tv3可以與tv2頂部對(duì)其勾哩,效果也是一樣的抗蠢。
二、間距
- layout_goneMarginStart
- layout_goneMarginEnd
- layout_goneMarginLeft
- layout_goneMarginTop
- layout_goneMarginRight
- layout_goneMarginBottom
表示當(dāng)前控件參考的控件隱藏時(shí)對(duì)應(yīng)的間距思劳,如果參考控件未隱藏該設(shè)置不會(huì)生效迅矛。
以下代碼表示tv1正常顯示多時(shí)候,tv2左邊距離tv1 100dp潜叛,如果tv1隱藏了秽褒,tv2左邊距為0
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
...
/>
<TextView
android:id="@+id/tv2"
...
android:layout_marginStart="100dp"
app:layout_goneMarginStart="0dp"
app:layout_constraintTop_toTopOf="@id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>
三、尺寸大小
1. 權(quán)重比
主要依賴于以下兩個(gè)屬性:
- app:layout_constraintHorizontal_weight
- app:layout_constraintVertical_weight
默認(rèn)情況下各控件的權(quán)重都是相等的威兜,以下代碼表示tv1销斟、tv2和tv3三等分ConstraintLayout的寬度
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
android:layout_width="0dp"
...
app:layout_constraintEnd_toStartOf="@id/tv2"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
...
app:layout_constraintEnd_toStartOf="@id/tv3"
app:layout_constraintStart_toEndOf="@id/tv1"
/>
<TextView
android:id="@+id/tv3"
android:layout_width="0dp"
...
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
如果需要非等分,使用layout_constraintHorizontal_weight或者layout_constraintVertical_weight屬性調(diào)整即可椒舵,以下代碼表示tv1蚂踊、tv2和tv3按照3:2:1的比例占滿ConstraintLayout的寬度
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
android:layout_width="0dp"
...
app:layout_constraintEnd_toStartOf="@id/tv2"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
...
app:layout_constraintEnd_toStartOf="@id/tv3"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toEndOf="@id/tv1"/>
<TextView
android:id="@+id/tv3"
android:layout_width="0dp"
...
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/tv2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2. 百分比
百分比需要滿足下面三個(gè)條件:
- 寬或高設(shè)置成0dp
- 寬或高默認(rèn)值設(shè)置成百分比
- app:layout_constraintWidth_default="percent"
- app:layout_constraintHeight_default="percent"
- 寬或高百分比的值(取值范圍0~1)
- app:layout_constraintWidth_percent
- app:layout_constraintHeight_percent
這里的百分比是指占父控件的百分比
以下代碼表示Textview寬度為ConstraintLayout寬度的50%
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
...
android:layout_width="0dp"
app:layout_constraintHeight_default="percent"
app:layout_constraintWidth_percent="0.5"/>
</androidx.constraintlayout.widget.ConstraintLayout>
3. 寬高比
百分比需要滿足下面兩個(gè)條件:
a. 寬或高至少有一個(gè)設(shè)置成0dp
b. 通過(guò)app:layout_constraintDimensionRatio設(shè)置寬高比
這里layout_constraintDimensionRatio寬高的取值有以下4種形式:
- 16:9 表示寬高比為16:9
- 0.2 表示寬高比為1:5
- H,16:9 表示寬高比為9:16
- W,16:9 表示寬高比為16:9
以下代碼表示Textview的寬高比為2:1
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
...
android:layout_height="0dp"
app:layout_constraintDimensionRatio="2:1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
高級(jí)用法
一、強(qiáng)制約束
1. 應(yīng)用場(chǎng)景
使用wrap_content笔宿,但仍要強(qiáng)制執(zhí)行約束以限制結(jié)果尺寸犁钟,比如一個(gè)Textview的寬度是根據(jù)文字內(nèi)容自適應(yīng)的,文字內(nèi)容可能很短也可能很長(zhǎng)泼橘,當(dāng)文字內(nèi)容很長(zhǎng)的時(shí)候可能會(huì)打破原先的約束涝动,比如本來(lái)在在某個(gè)控件的左邊,但是隨著文字內(nèi)容的增長(zhǎng)會(huì)越界炬灭!
2. 使用方式
- layout_constrainedWidth="true|false"
- layout_constrainedHeight="true|false"
使用以上兩個(gè)屬性來(lái)強(qiáng)制控件的寬或高嚴(yán)格執(zhí)行相應(yīng)的約束條件
3. 示例
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
...
android:layout_width="wrap_content"
app:layout_constraintRight_toLeftOf="@id/tv2"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="@+id/tv2"
...
android:layout_width="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tv1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
以上代碼實(shí)現(xiàn)的是tv1在tv2的左邊醋粟,隨著tv1內(nèi)容不斷增加,tv1的右邊會(huì)越過(guò)tv2的左邊,如果想限制不管tv1內(nèi)容怎么增加都不會(huì)越過(guò)tv2的左邊昔穴,則可增加layout_constrainedWidth="true"即可
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
...
android:layout_width="wrap_content"
app:layout_constrainedWidth="true"
app:layout_constraintRight_toLeftOf="@id/tv2"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="@+id/tv2"
...
android:layout_width="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tv1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
二镰官、Barrier
1. 應(yīng)用場(chǎng)景
當(dāng)某個(gè)控件的約束想以一組控件為參考點(diǎn),并且始終不越界
2. 使用方式
- app:barrierDirection="start|left|top|right|end|bottom"
- app:constraint_referenced_ids="tv1,tv2"
3. 示例
以下代碼表示以tv1和tv2的底部為一個(gè)屏障吗货,tv3始終在tv1和tv2下面泳唠,即使tv1和tv2全部都消失
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom"
app:constraint_referenced_ids="tv1,tv2" />
<TextView
android:id="@+id/tv1"
...
/>
<TextView
android:id="@+id/tv2"
...
/>
<TextView
android:id="@+id/tv3"
...
app:layout_constraintTop_toBottomOf="@id/barrier"/>
</androidx.constraintlayout.widget.ConstraintLayout>
三、 Guideline
1. 應(yīng)用場(chǎng)景
布局參考線可以作為其他控件布局約束的參考宙搬,但不會(huì)顯示出來(lái)
2. 使用方式
參考線的方向笨腥,可分為水平和豎直兩個(gè)方向:
- android:orientation="vertical|horizontal"
參考線的位置:
- app:layout_constraintGuide_begin="100dp"
- app:layout_constraintGuide_end="100dp"
- app:layout_constraintGuide_percent="0.5"
3. 示例
以下代碼表示以ConstraintLayout寬度的中心點(diǎn)為參考線,tv1與參考線左對(duì)齊
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tv1"
...
app:layout_constraintLeft_toLeftOf="@id/guideline"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
四勇垛、Group
1. 應(yīng)用場(chǎng)景
將某幾個(gè)控件歸為一組動(dòng)態(tài)進(jìn)行顯示或隱藏控制
2. 使用方式
需要?dú)w為一組控件的ID
- app:constraint_referenced_ids="tv1,tv2"
3. 示例
以下代碼表示將tv1和tv2兩個(gè)textview歸為一組脖母,并設(shè)置為隱藏
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="tv1,tv2"/>
<TextView
android:id="@+id/tv1"
...
/>
<TextView
android:id="@+id/tv2"
...
/>
</androidx.constraintlayout.widget.ConstraintLayout>
五、Chain
Chain可以很容易達(dá)到其他布局管理器不容易實(shí)現(xiàn)闲孤,甚至無(wú)法實(shí)現(xiàn)的樣式
1. 應(yīng)用場(chǎng)景
某幾個(gè)控件之間首位相接谆级,排列方式有特殊要求
2. 使用方式
- layout_constraintHorizontal_chainStyle="spread|spread_inside|packed"
- layout_constraintVertical_chainStyle="spread|spread_inside|packed"
chainStyle取值:
- spread: 控件均勻分布,即控件之間(包括邊框)間距相同
- spread_inside: 第一個(gè)和最后一個(gè)控件固定在鏈兩端的約束邊界上讼积,其余控件均勻分布肥照,即控件內(nèi)部之間間距相同
- packed: 控件打包在一起(在考慮外邊距之后)。 然后勤众,您可以通過(guò)更改鏈的頭視圖偏差調(diào)整整條鏈的偏差(左/右或上/下)舆绎。
3. 示例
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00897B"
android:gravity="center"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="1111"
android:textColor="#fff"
android:textSize="20sp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#3700B3"
android:gravity="center"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="2222"
android:textColor="#fff"
android:textSize="20sp"
app:layout_constraintBaseline_toBaselineOf="@id/tv1"
app:layout_constraintEnd_toStartOf="@id/tv3"
app:layout_constraintStart_toEndOf="@id/tv1" />
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FB8C00"
android:gravity="center"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="3333"
android:textColor="#fff"
android:textSize="20sp"
app:layout_constraintBaseline_toBaselineOf="@id/tv1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv2" />
</androidx.constraintlayout.widget.ConstraintLayout>
綜合實(shí)踐
使用ConstraintLayout實(shí)現(xiàn)以下布局们颜,要求:
- 兩個(gè)textview橫向并排顯示吕朵,即一左一右
- 兩個(gè)textview的寬度均根據(jù)文字內(nèi)容自適應(yīng)
- 兩個(gè)textview均左對(duì)齊
- 右邊textview內(nèi)容全展示(文字內(nèi)容最多不會(huì)超過(guò)單行寬度)
- 顯示不下時(shí)左邊textview內(nèi)容尾部顯示省略號(hào)
最終效果圖
實(shí)現(xiàn)代碼:
<androidx.constraintlayout.widget.ConstraintLayout
...
>
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00897B"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="AAAAA"
android:textColor="#fff"
android:textSize="20sp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv2"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FB8C00"
android:ellipsize="end"
android:gravity="center"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:singleLine="true"
android:text="BBBB"
android:textColor="#fff"
android:textSize="20sp"
app:layout_constraintBaseline_toBaselineOf="@id/tv1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>