約束布局ConstraintLayout 使用

ConstraintLayoutRelativeLayout 相似,其中所有的視圖均根據(jù)同級(jí)視圖與父布局之間的關(guān)系進(jìn)行布局,但其靈活性要高于 RelativeLayout,適合創(chuàng)建復(fù)雜的大型布局。

官方教程地址:https://developer.android.google.cn/training/constraint-layout

一、基本使用

1.1 添加到項(xiàng)目中

  1. 在項(xiàng)目根目錄的 build.gradle文件中聲明:

        repositories {
            google()
        }
        
    
  2. 將該庫作為依賴項(xiàng)添加到項(xiàng)目的 build.gradle 文件中,如以下示例所示

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.0.4"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha07"
    }
    

1.2 基本使用

約束條件如下:


未命名文件.png

例如下面這個(gè)簡單的布局,有個(gè)按鈕位于屏幕左上角


布局1.png

對(duì)應(yīng)的布局代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <Button
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test"/>
</androidx.constraintlayout.widget.ConstraintLayout>

其中 parent 代表的是父布局。

注意:在約束性布局中,除非寬高設(shè)置成 match_parent,否則其他場景都需要設(shè)置 (上 || 下)&& (左 || 右) 的約束條件, 不然編譯器會(huì)出現(xiàn)報(bào)錯(cuò)警告。

二、布局居中

水平居中:


水平居中.png

設(shè)置 constraintLeftconstraintRight,根據(jù)左右兩邊約束的視圖居中。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <Button
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test"/>
</androidx.constraintlayout.widget.ConstraintLayout>

垂直居中:


豎直居中.png

設(shè)置 constraintTopconstraintBottom,根據(jù)上下約束的視圖居中。

  <Button
    android:id="@+id/btn"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test"/>

居中設(shè)置偏移比例

設(shè)置 layout_constraintVertical_biaslayout_constraintHorizontal_bias

layout_constraintVertical_bias:垂直偏移,范圍 0 ~ 1 ,0代表最上方,1代表最下方

layout_constraintHorizontal_bias:水平偏移,范圍 0 ~ 1,0代表最左邊,1代表最右邊

水平偏移.png
垂直偏移.png

三、鏈條控制線性組

設(shè)置 layout_constraintHorizontal_chainStylelayout_constraintVertical_chainStyle 通過鏈條方式控制一組控件,例如:

鏈條.png

1 Spread:視圖均勻分布,默認(rèn)該屬性

2 Packed:視圖打包一起

3 Spread inside:第一個(gè)和最后一個(gè)視圖固定在鏈條兩端

4 Weighted:權(quán)重布局,layout_width = 0dp,layout_constraintHorizontal_weight設(shè)置權(quán)重

鏈?zhǔn)且唤M視圖,這些視圖通過 雙向位置約束條件相互鏈接到一起,即上圖 鏈中的視圖可以垂直或水平分布。
由鏈條的第一個(gè)視圖設(shè)置 chainStyle 即可。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <Button
    android:id="@+id/btn1"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/btn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="btn1"/>

  <Button
    android:id="@+id/btn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/btn1"
    app:layout_constraintRight_toLeftOf="@id/btn3"
    app:layout_constraintTop_toTopOf="@id/btn1"
    android:text="btn2"/>

  <Button
    android:id="@+id/btn3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/btn2"
    app:layout_constraintTop_toTopOf="@id/btn1"
    app:layout_constraintRight_toRightOf="parent"
    android:text="btn3"
    />

  <Button
    android:id="@+id/btn4"
    android:layout_marginTop="64dp"
    app:layout_constraintTop_toBottomOf="@id/btn1"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/btn5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="btn4"
    app:layout_constraintHorizontal_chainStyle="packed"/>

  <Button
    android:id="@+id/btn5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/btn4"
    app:layout_constraintRight_toLeftOf="@id/btn6"
    app:layout_constraintTop_toTopOf="@id/btn4"
    android:text="btn5"/>

  <Button
    android:id="@+id/btn6"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/btn5"
    app:layout_constraintTop_toTopOf="@id/btn4"
    app:layout_constraintRight_toRightOf="parent"
    android:text="btn6"/>

  <Button
    android:id="@+id/btn7"
    android:layout_marginTop="64dp"
    app:layout_constraintTop_toBottomOf="@id/btn4"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/btn8"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="btn7"
    app:layout_constraintHorizontal_chainStyle="spread_inside"/>

  <Button
    android:id="@+id/btn8"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/btn7"
    app:layout_constraintRight_toLeftOf="@id/btn9"
    app:layout_constraintTop_toTopOf="@id/btn7"
    android:text="btn8"/>

  <Button
    android:id="@+id/btn9"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/btn8"
    app:layout_constraintTop_toTopOf="@id/btn7"
    app:layout_constraintRight_toRightOf="parent"
    android:text="btn9"/>

  <Button
    android:id="@+id/btn10"
    android:layout_marginTop="64dp"
    app:layout_constraintTop_toBottomOf="@id/btn7"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/btn11"
    android:layout_width="0dp"
    app:layout_constraintHorizontal_weight="1"
    android:layout_height="wrap_content"
    android:text="btn10"
    app:layout_constraintHorizontal_chainStyle="spread_inside"/>

  <Button
    android:id="@+id/btn11"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintHorizontal_weight="2"
    app:layout_constraintLeft_toRightOf="@id/btn10"
    app:layout_constraintRight_toLeftOf="@id/btn12"
    app:layout_constraintTop_toTopOf="@id/btn10"
    android:text="btn11"/>

  <Button
    android:id="@+id/btn12"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintHorizontal_weight="2"
    app:layout_constraintLeft_toRightOf="@id/btn11"
    app:layout_constraintTop_toTopOf="@id/btn10"
    app:layout_constraintRight_toRightOf="parent"
    android:text="btn12"/>
</androidx.constraintlayout.widget.ConstraintLayout>

四、引導(dǎo)線約束

可以添加垂直或水平的引導(dǎo)線來約束視圖,并且應(yīng)用用戶看不到該引導(dǎo)線。 可以根據(jù)相對(duì)于布局邊緣的 dp 單位或百分比在布局中定位引導(dǎo)線。


引導(dǎo)線.png
  <androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintGuide_percent="0.5"/>

  <Button
    android:id="@+id/btn1"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_width="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/guideline"
    android:layout_height="wrap_content"
    android:text="btn1"/>

引導(dǎo)線也是一個(gè)控件,只是不會(huì)顯示出來,orientation 設(shè)置垂直或水平方向的引導(dǎo)線,layout_constraintGuide_percent 支持百分比定位引導(dǎo)線,范圍 0 ~ 1。

由于 layout_margin 無法設(shè)置百分比,我們可以通過 Guideline 替代實(shí)現(xiàn)。

五、實(shí)現(xiàn)覆蓋布局效果

覆蓋1.png

上圖這種覆蓋方式通過布局順序?qū)崿F(xiàn)的,btn2 控件布局中在 btn1 控件的下方。

由于 ConstraintLayout 布局中無法設(shè)置負(fù)數(shù)的 margin ,所以如果想覆蓋控件的上半部分,可以通過引導(dǎo)線等輔助實(shí)現(xiàn)。

覆蓋2.png

<androidx.constraintlayout.widget.Guideline
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.5"
    android:id="@+id/space"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

  <Button
    android:background="@color/colorAccent"
    android:layout_marginTop="32dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn1"
    android:text="btn1"
    app:layout_constraintTop_toBottomOf="@id/space"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"/>

  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn2"
    android:text="btn2"
    android:layout_marginStart="64dp"
    android:background="@color/reset_totp_indicator_color"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/space"/>

六、百分比布局

layout_constraintHeight_percentlayout_constraintWidth_percent 支持通過百分比設(shè)置控件的寬高,范圍 0 ~ 1 。

百分比.png

  <Button
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:text="btn1"
    app:layout_constraintHeight_percent="0.3"
    app:layout_constraintWidth_percent="0.5"
    android:background="@color/reset_totp_indicator_color"/>

layout_widthlayout_height 必須設(shè)置成 0dp,才可以生效。

七、約束失效問題

當(dāng)設(shè)置 wrap_content 再設(shè)置約束條件時(shí)會(huì)發(fā)現(xiàn)約束條件失效了,例如:

約束失效.png

 <TextView
    android:text="sdfsfdsdfsdfssdfsdfsdfdsfdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tv_username"
    android:textColor="@color/find_pass_text_color"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/btn1"
    android:maxLines="1"
    android:ellipsize="end"
    app:layout_constraintHorizontal_chainStyle="packed"
    app:layout_constraintHorizontal_bias="0"
    />

  <Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:text="btn1"
    app:layout_constraintHeight_percent="0.3"
    app:layout_constraintWidth_percent="0.5"
    android:background="@color/colorAccent"/>

雖然設(shè)置了約束條件 app:layout_constraintRight_toLeftOf="@id/btn1",但實(shí)際并沒有生效。

需要設(shè)置 layout_constrainedWidth 為true,修改后效果如下:

約束失效2.png

  <TextView
    android:text="sdfsfdsdfsdfssdfsdfsdfdsfdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tv_username"
    android:textColor="@color/find_pass_text_color"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/btn1"
    android:maxLines="1"
    android:ellipsize="end"
    app:layout_constraintHorizontal_chainStyle="packed"
    app:layout_constraintHorizontal_bias="0"
    app:layout_constrainedWidth="true"
    />

  <Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:text="btn1"
    app:layout_constraintHeight_percent="0.3"
    app:layout_constraintWidth_percent="0.5"
    android:background="@color/colorAccent"/>

八、設(shè)置視圖最大、最小尺寸

有時(shí)候適配不同屏幕時(shí),我們不希望尺寸隨著屏幕變大而無限拉伸,這時(shí)候可以通過 layout_constraintWidth_maxlayout_constraintHeight_max,layout_constraintWidth_min,layout_constraintHeight_min 這幾個(gè)設(shè)置寬高的最大或最小值。

需要配合百分比布局 layout_constraintWidth_percent 才可以生效。

限制寬高1.png
  <Button
    android:id="@+id/btn1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    android:text="btn1"
    android:background="@color/colorAccent"
    app:layout_constraintWidth_percent="0.85"
    />

設(shè)置寬度最大值為 200dp,修改后顯示如下:


限制寬高2.png
  <Button
    android:id="@+id/btn1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    android:text="btn1"
    android:background="@color/colorAccent"
    app:layout_constraintWidth_percent="0.85"
    app:layout_constraintWidth_max="200dp"
    />
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容