ConstraintLayout 約束布局

參考
Android新特性介紹,ConstraintLayout完全解析
史上最全ConstraintLayout使用詳解

概述:

約束布局,各個(gè)控件可以依據(jù)某些約束法則排列

位置功能:

相對(duì)位置

相對(duì)父控件位置

layout_constraintBottom_toBottomOf 這樣的結(jié)構(gòu),可以記憶為
layout_constraintBottom 本控件位置指示 底部
toBottomOf 相對(duì)的控制位置指示 底部
app:layout_constraintBottom_toBottomOf="parent" 代表 本控件的底部位置和parent父控件的底部位置一致
一般而已,我們有Bottom,Top,Start,End 幾個(gè)類型,其中Start,End和Left,Right是一致的,只是因?yàn)橛行﹪?guó)家的left和right不是一致的,所以統(tǒng)一用Start,End代表。雖然Start,End和Left,Right是一致的,但是要注意Start,End是一對(duì),Left,Right是一對(duì),不可以混搭使用。

app:layout_constraintBottom_toBottomOf="parent" //本控件的底部位置和parent父控件的底部位置一致
app:layout_constraintEnd_toEndOf="parent"http://本控件的結(jié)束位置和parent父控件的結(jié)束位置一致
app:layout_constraintStart_toStartOf="parent"http://本控件的開始位置和parent父控件的開始位置一致
app:layout_constraintTop_toTopOf="parent"http://本控件的頭部位置和parent父控件的頭部位置一致

下面代碼,就是TextView的位置相對(duì)于父控件位置上下左右都是一致,因?yàn)樗闹芏技s束了,結(jié)果就是再中間

<androidx.constraintlayout.widget.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=".activity.MainActivity">
  <TextView
    android:id="@+id/imageView"
    android:text="TextView 1"
    android:background="@color/colorAccent"
    android:layout_width="200dp"
    android:layout_height="200dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
1.png

如果控件沒有約束四邊,就會(huì)有不同的效果,如下圖,只約束了兩邊,控件的下方和父控件一致,控件的右邊和父控件一致,就會(huì)導(dǎo)致控制整個(gè)變成右下


2.png

相對(duì)某個(gè)控件位置

和相對(duì)于父控件位置很相似,核心代碼都是layout_constraintBottom_toBottomOf,只是后面變成="
@+id/viewId"
如下圖,就是TextView2底部和TextView1的頭部對(duì)齊,開始位置和結(jié)束位置和父控件對(duì)其

3.png

偏移量

當(dāng)給控件增加了Top和Bottom的約束,就可以豎向產(chǎn)生偏移量,如果是增加了Start和End約束,就可以橫向的偏移量。在可視化的屬性里面,就是這里的滑動(dòng)按鈕


4.png

如果是在代碼里面,就是layout_constraintVertical_bias和layout_constraintHorizontal_bias,后面參數(shù)是百分比


5.png

控件大小

在ConstraintLayout里面,控件大小總共有三種方式

Fixed 固定大小

layout_width和layout_height 里面填寫固定的大小就可以,在可視化的屬性里面(Attributes)看到的樣子就是這樣


6.png

包裹大小 wrap_content

layout_width和layout_height 里面都是wrap_content,就是跟隨控件里面的內(nèi)容自動(dòng)變化控件大小,在可視化的屬性里面(Attributes)看到的樣子就是這樣


7.png

匹配約束 Match Constraints

就是根據(jù)空間約束的規(guī)則來分配剩余空間,有三種模式,分別是spread,percent,wrap,通過layout_constraintHeight_default和layout_constraintWidth_default字段來標(biāo)注是什么屬性,一般是spread。從可視化效果來看,就是Match Constraints,如下圖,從代碼來看就是layout-wight和layout-height都是0,自動(dòng)是Match Constraints模式。


8.png

spread 默認(rèn)

有點(diǎn)類似于match parent,不過match parent是相對(duì)于父控件,而Match Constraints是相對(duì)于約束控件來說,從可視化的屬性里面(Attributes)來看,TextView2開始和結(jié)束是相對(duì)于父控件而已,所以當(dāng)wight是Match Constraints的時(shí)候,寬會(huì)填滿整個(gè)父控件,而高雖然是相對(duì)于父控件,底部是相對(duì)于TextView1的top,當(dāng)高變成Match Constraints的時(shí)候,會(huì)占據(jù)父控件Top到TextView1的top,效果如下圖


9.png

而此時(shí),如果看代碼其實(shí)TextView2的layout-wight和layout-height都是0,就自動(dòng)是Match Constraints,而且是layout_constraintHeight_default和layout_constraintWidth_default加不加效果一樣


10.png

percent:按照父布局百分比設(shè)置

控件的尺寸是按照父控件的尺寸的百分比居中限制,需要和layout_constraintHeight_percent|layout_constraintWidth_percent配合使用,如圖,TextView是父控件就是ConstraintLayout,100%應(yīng)該是ConstraintLayout一樣大小。代碼中l(wèi)ayout_constraintHeight_percent|layout_constraintWidth_percent都是0.5,按照ConstraintLayout的50%顯示,并且居中


11.png

wrap:匹配內(nèi)容大小但是不超過約束的限制

就是能按照內(nèi)容大小去匹配,并且不能超過約束的配置,主要是對(duì)比layout_width = "wrap_content"|layout_height = "wrap_content"來的。
如下面代碼,tv1和tv2都是一樣的大小,包裹1234567789的大小,然后又給了另外一層限制,都是距離左右邊距是200dp,看tv1的效果,早就突破了這長(zhǎng)度,優(yōu)先了內(nèi)容的展示1234567789,實(shí)際上距離左右邊距沒有200dp。(tv1如果想要和tv2一樣的效果,可以通過代碼app:layout_constrainedWidth="true"|app:layout_constrainedHeight="true"設(shè)置)
而tv2,優(yōu)先保證了保持左右邊距是200dp,內(nèi)容展示不全


12.png
<androidx.constraintlayout.widget.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">

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_marginStart="150dp"
        android:layout_marginEnd="150dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="1234567789"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="150dp"
        android:layout_marginEnd="150dp"
        app:layout_constraintHeight_default="wrap"
        app:layout_constraintWidth_default="wrap"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintWidth_percent="0.5"
        android:background="@color/colorAccent"
        android:text="1234567789"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

比例寬高

app:layout_constraintDimensionRatio="1:1"|app:layout_constraintDimensionRatio="0.5"可以設(shè)置款高比例,但是需要至少款高有一個(gè)為0。兩種設(shè)置方式,1:1代表寬度和高度之間的比率,也可以用0.5等浮點(diǎn)型表示

<androidx.constraintlayout.widget.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">
    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:3"
        app:layout_constraintHeight_default="wrap"
        app:layout_constraintWidth_default="wrap"
        android:background="@color/colorAccent"
        android:text="1234567789"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

效果展示是


13.png

輔助線 Guidelines

自身設(shè)置

可以建立一條輔助線,將控件用于輔助線約束,可以在可視化的界面直接拖拽,通過點(diǎn)擊下面小三角來改變約束位置和位置數(shù)值


14.gif

通過代碼來看,orientation控制是橫還是豎
layout_constraintGuide_begin控制位置,如果是距離開始是位置是layout_constraintGuide_begin,如果是距離結(jié)束的位置是layout_constraintGuide_end;如果是變成百分比,是layout_constraintGuide_percent="0.5"

<androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="206dp" />

其余控件相對(duì)位置

就是直接通過layout_constraintBottom_toBottomOf等約束,這次是textView1的結(jié)束和guideline1對(duì)齊,textView2的開始和guideline1對(duì)齊,也就是textView1和textView2分別在guideline1兩邊

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="200dp"
        android:background="@color/colorAccent"
        android:text="TextView 1"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/guideline1"
        />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="100dp"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:text="TextView2"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline1"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />
15.png

自動(dòng)化約束

自動(dòng)連接 Autoconnect

當(dāng)開啟了Autoconnect的時(shí)候,也就是可視化頁面上面磁鐵的按鈕,一般情況下會(huì)關(guān)閉,拖動(dòng)控件到合適的位置,會(huì)自動(dòng)添加約束。


16.gif

推斷約束 Infer Constraints

我們可以把控件拖到各自位置,按照想要的布局排好,然后點(diǎn)擊Infer Constraints按鈕,也就是發(fā)光棒的樣子的按鈕,會(huì)自動(dòng)推斷當(dāng)前頁面上控件布局,給所有控件添加約束


17.gif

基線對(duì)齊

可以通過layout_constraintBaseline_toBaselineOf讓兩個(gè)控件幾線對(duì)齊,比如,我們又text1和text2,text2的開始位置和text1的結(jié)束位置對(duì)齊,此時(shí),我們加上layout_constraintBaseline_toBaselineOf,可以讓text1和text2的基線對(duì)齊


18.gif

角度約束

可以約束某個(gè)控件相對(duì)于某個(gè)控件的角度,比如text2在text1的100dp外90°的方向。0°是正上方,順時(shí)針旋轉(zhuǎn),所以text2在text1的右邊。


19.png

代碼主要是這個(gè)三個(gè)

app:layout_constraintCircle="@id/tv1"  //目標(biāo)控件的id
app:layout_constraintCircleAngle="90"  //對(duì)于目標(biāo)控件的角度,負(fù)數(shù)無效
app:layout_constraintCircleRadius="100dp"  //到目標(biāo)控件中間的距離
<androidx.constraintlayout.widget.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">

    <TextView
        android:id="@+id/tv1"
        android:background="@color/colorPrimary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text1"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tv2"
        android:text="Text2"
        android:textSize="20sp"
        android:background="@color/colorAccent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintCircle="@id/tv1"
        app:layout_constraintCircleAngle="90"
        app:layout_constraintCircleRadius="100dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

控件內(nèi)邊距、外邊距、GONE Margin

內(nèi)外邊距

這個(gè)和別的控件一模一樣,主要是通過layout_margin和padding來控制的

GONE Margin

這個(gè)屬性比較奇怪,當(dāng)依賴的目標(biāo)是gone的時(shí)候,本目標(biāo)的GONE Margin才會(huì)生效,而且要注意方向,比如設(shè)置了layout_constraintTop_toTopOf方向約束,那么layout_goneMarginTop才會(huì)生效
如圖,依賴的控件沒有g(shù)one的時(shí)候,goneMargin沒有效果


21.png

等控件tv1隱藏


22.png

Barrier(屏障)

這個(gè)和基線一樣,是個(gè)不顯示在屏膜上的,可以對(duì)多個(gè)控件進(jìn)行一個(gè)自動(dòng)合適的適配
比如下圖,ABC三個(gè)控件,我希望B是放在A和C的右側(cè),但是A和C里面的文字不定的,不知道哪個(gè)長(zhǎng)一點(diǎn),如果我設(shè)定B是在A的右側(cè),當(dāng)C過長(zhǎng)的時(shí)候,可能就覆蓋了B,雖然可以使用一個(gè)控件包裹AC來完成,但是多了一層,可以使用Barrier

23.png

Barrier是一個(gè)控件,控件并不顯示在頁面上, 只是為了約束別的控件,主要有兩個(gè)屬性


<!--  用于控制Barrier相對(duì)于給定的View的位置  -->
app:barrierDirection="top|bottom|left|right|start|end"  
 
<!--  取值是要依賴的控件的id,Barrier將會(huì)使用ids中最大的一個(gè)的寬/高作為自己的位置  -->
app:constraint_referenced_ids="id,id"

比如如下代碼,需要依賴的控件是tvA,tvB,位于這些控件的end。會(huì)根據(jù)tvA,tvB自適應(yīng),如果tvA比較長(zhǎng),就是tvA后面,tvB比較長(zhǎng),就是tvB后面。

<androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        app:constraint_referenced_ids="tvA,tvC"
        app:barrierDirection="end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

效果圖如下


24.gif

可以通過把控件B放在Barrier右側(cè)來實(shí)現(xiàn)我們要的功能


25.gif

Group(組)

就是可以把控件加入一個(gè)組,對(duì)一組控件進(jìn)行顯示或者隱藏操作,同樣不顯示在頁面上,主要就是通過constraint_referenced_ids="id,id……"將控件Id添加進(jìn)去

<androidx.constraintlayout.widget.Group
        android:visibility="gone"
        app:constraint_referenced_ids="tvA,tvB,tvC"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

Placeholder(占位符)

可以在頁面上提前部署一個(gè)占位符的控件,通過調(diào)用這個(gè)占位符的setContent(int id),可以將別的控件移動(dòng)到占位符控件的位置

<androidx.constraintlayout.widget.Placeholder
        android:id="@+id/place"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintEnd_toEndOf="parent" />

Chains(鏈)

把一系列控件首位相連進(jìn)行排列,會(huì)自動(dòng)形成鏈,默認(rèn)是spread,均分剩余空間,有水平鏈或者垂直鏈,代碼如下

<androidx.constraintlayout.widget.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">

    <TextView
        android:id="@+id/tvA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="A"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvB"
        app:layout_constraintStart_toStartOf="parent" />
    <TextView
        android:id="@+id/tvB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="B"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvC"
        app:layout_constraintStart_toEndOf="@id/tvA" />
    <TextView
        android:id="@+id/tvC"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="C"
        android:textSize="40sp"
        app:layout_constraintStart_toEndOf="@id/tvB"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

效果呈現(xiàn)就是三個(gè)控件均勻分布


20.png

layout_constraintHorizontal_chainStyle和layout_constraintVertical_chainStyle分別對(duì)水平和垂直鏈設(shè)置模式,模式可選的值有:spread、packed、spread_inside。
spread:就是默認(rèn)的均分
packed:所有控件緊貼在一起


27.png

spread_inside:兩側(cè)的控件貼近兩邊,剩下的控件均分


28.png

鏈還可以設(shè)置權(quán)重,通過layout_constraintHorizontal_weight|layout_constraintVertical_weight來設(shè)置
代碼如下

<androidx.constraintlayout.widget.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">

    <TextView
        android:id="@+id/tvA"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="A"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvB"
        app:layout_constraintStart_toStartOf="parent" />
    <TextView
        android:id="@+id/tvB"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="B"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvC"
        app:layout_constraintStart_toEndOf="@id/tvA" />
    <TextView
        android:id="@+id/tvC"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="C"
        android:textSize="40sp"
        app:layout_constraintStart_toEndOf="@id/tvB"
        app:layout_constraintEnd_toStartOf="@id/tvD"/>
    <TextView
        android:id="@+id/tvD"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="D"
        android:textSize="40sp"
        app:layout_constraintStart_toEndOf="@id/tvC"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

效果圖


29.png

Flow 流式布局

一般鏈約束需要控件首尾相連,但是可以使用Flow,會(huì)默認(rèn)將所有控件約束起來。Flow本身不展示在頁面上,也是一種虛擬布局。需要的constraintlayout 2.0才有,如果沒有,需要去build.gradle看一下constraintlayout的版本
通過app:constraint_referenced_ids="id1,id2,id3……"等設(shè)置要進(jìn)行布局的控件id
通過app:flow_wrapMode=""來設(shè)置排列方式,none是默認(rèn),就是連續(xù)排列,超出的部分不可見。chian是超出部分自動(dòng)換行,同行的會(huì)平分。aligned是超出部分自動(dòng)換行,同行會(huì)一邊靠齊。
通過orientation屬性,決定是垂直還是水平。
常規(guī)使用如下,TextView的id就是A,B,C,D,E,文本也是,通過Flow的app:constraint_referenced_ids將id添加,app:flow_wrapMode可以寫也可以不寫,默認(rèn)就是none。


30.png

排列方式:app:flow_wrapMode

none:默認(rèn)屬性,就是連續(xù)平分空間的排列,如果超出的部分則不可見,代碼如下

<androidx.constraintlayout.widget.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">
    <TextView
        android:id="@+id/A"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="A"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/B"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="B"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/C"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="C"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/D"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="D"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/E"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="E"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/F"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="F"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/G"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="G"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/H"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="H"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flow_wrapMode="none"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />


</androidx.constraintlayout.widget.ConstraintLayout>

效果圖如下


31.png

chain:超出部分自動(dòng)換行,并且所有控件等分

<androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flow_wrapMode="chain"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果圖


32.png

aligned:超出部分也自動(dòng)換行,但是不是等分而是靠一邊顯示

<androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flow_wrapMode="aligned"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果圖


33.png

排列方向:orientation

通過orientation為horizontal|vertical可以控制是水平還是垂直,orientation為vertical是垂直,默認(rèn)是水平

<androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果圖


34.png

間隔距離:flow_horizontalGap|flow_verticalGap

通過flow_horizontalGap|flow_verticalGap可以設(shè)置各個(gè)控件水平或者垂直的間隔距離,要注意一下是水平還是垂直方向的排列,下面代碼,是垂直排列,而且間隔是20dp,可以看到控件不在緊緊貼在一起了。

<androidx.constraintlayout.helper.widget.Flow
        app:flow_verticalGap="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果圖


35.png

每條鏈配置

當(dāng)flow_wrapMode的值是chian或aligned時(shí),通過flow_horizontalStyle等屬性,可以對(duì)每條鏈或者所有鏈進(jìn)行配置,有三種模式,和鏈一樣
spread:均分排列


36.png

packed:貼在一起居中


37.png

spread_inside:緊貼兩邊,其余的均分
38.png

app:flow_horizontalStyle="packed|spread|spread_inside" 所有水平鏈的配置

app:flow_verticalStyle="packed|spread|spread_inside" 所有垂直鏈的配置
app:flow_firstHorizontalStyle="packed|spread|spread_inside" 第一條水平鏈的配置,其他條不生效
app:flow_firstVerticalStyle="packed|spread|spread_inside" 第一條垂直鏈的配置,其他條不生效
app:flow_lastHorizontalStyle="packed|spread|spread_inside" 最后一條水平鏈的配置,其他條不生效
app:flow_lastVerticalStyle="packed|spread|spread_inside" 最后一條垂直鏈的配置,其他條不生效

對(duì)齊約束

控件在Flow里面,默認(rèn)是居中對(duì)齊的,但是控件大小不一樣,可以設(shè)置不同的對(duì)齊方式。通過flow_verticalAlign|flow_horizontalAlign來控制。如果是水平鏈?zhǔn)峭ㄟ^flow_verticalAlign控制,如果是垂直鏈?zhǔn)峭ㄟ^flow_horizontalAlign控制。下面都是以水平鏈做展示
top:頭部對(duì)齊

<androidx.constraintlayout.helper.widget.Flow
        app:flow_horizontalGap="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="A,B,C,D,E,F"
        app:flow_verticalAlign="top" />
39.png

bottom:底部對(duì)齊


40.png

center:居中對(duì)齊


41.png

baseline:基線對(duì)齊
要注意一下,當(dāng)其中一個(gè)TextView里面的文字F不在中間的時(shí)候,是根據(jù)F的基線對(duì)齊的,如果是都是在中間,和center效果一樣
42.png

數(shù)量約束 flow_maxElementsWrap

可以通過flow_maxElementsWrap = "數(shù)量值"來約束一條鏈最大的數(shù)量,需要配合flow_wrapMode屬性使用,如下代碼,flow_maxElementsWrap約束了一條鏈最多4個(gè),配合了flow_wrapMode是多的靠一邊排列,如是none不行,顯示不出效果

<androidx.constraintlayout.helper.widget.Flow
        app:flow_horizontalGap="10dp"
        app:flow_wrapMode="aligned"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="A,B,C,D,E,F"
        app:flow_verticalAlign="center"
        app:flow_maxElementsWrap="4"/>

效果圖


43.png

Layer層布局

本質(zhì)上而已,這個(gè)控件是把可以把別的控件加載在它上面,變成一層一層的,它沒辦法自己設(shè)置位置,設(shè)置大小,跟著它上面的層自己調(diào)整,它不是虛擬的控件,可以被看見,如果它是最上面一層,會(huì)覆蓋所有的層。主要也是通過constraint_referenced_ids添加別的層的id。
下面代碼,雖然寫了Layer的位置和大小,但是全部失效,是跟著A和B控件來的,顏色沒有失效,可以看到。Layer是在A和B前面寫的,所有在最底層,如果在A和B后面就會(huì)覆蓋掉A和B。
constraint_referenced_ids的順序沒有任何影響,Layer的順序就是寫控件的順序。

<androidx.constraintlayout.widget.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">
    <androidx.constraintlayout.helper.widget.Layer
        android:background="@color/colorAccent"
        android:layout_width="300dp"
        android:layout_height="300dp"
        app:constraint_referenced_ids="A,B"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/A"
        android:layout_width="60dp"
        android:layout_height="90dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="A"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/B"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="B"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
</androidx.constraintlayout.widget.ConstraintLayout>

效果圖


44.png

ImageFilterButton & ImageFilterView

這兩個(gè)控件有點(diǎn)像ImageButton和ImageView的關(guān)系,有兩個(gè)特殊作用,再ImageFilterButton|ImageFilterView中都可以。下面主要用ImageFilterView測(cè)試

圓角

可以通過app:roundPercent設(shè)置圓角的比例,app:round設(shè)置大小

<androidx.constraintlayout.widget.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">

    <androidx.constraintlayout.utils.widget.ImageFilterView
        app:roundPercent="0.5"
        app:round="50dp"
        android:background="@color/colorAccent"
        android:layout_width="100dp"
        android:layout_height="100dp"/>
    
</androidx.constraintlayout.widget.ConstraintLayout>

效果圖


45.png

多層圖片

src可以設(shè)置第一層圖片,altSrc可以再設(shè)置一層圖片,再src上面,默認(rèn)是透明的,需要通過crossfade屬性來設(shè)置,0-1直接的值
效果圖如下,第一層圖片是Android的圖標(biāo),第二層圖片破了的圖片,crossfade是0.5


46.png

其余屬性調(diào)整

warmth屬性可以用來調(diào)節(jié)色溫
brightness屬性用來調(diào)節(jié)亮度
saturation屬性用來調(diào)節(jié)飽和度
contrast屬性用來調(diào)節(jié)對(duì)比度
這幾個(gè)屬性涉及到美術(shù)了,目前不太了解

MockView 原型圖軟件

這個(gè)控件,說可以來畫原型圖,id就是控件里面的文字,使用很簡(jiǎn)單

<androidx.constraintlayout.utils.widget.MockView
        android:id="@+id/MockView"
        android:layout_width="100dp"
        android:layout_height="100dp"/>

效果如下


47.png
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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