跟我一起學(xué)ConstraintLayout (1)

ConstraintLayout簡介

一種應(yīng)對復(fù)雜多層嵌套或復(fù)雜依賴關(guān)系的高效布局,解決相對布局中由于目標(biāo)控件隱藏導(dǎo)致的布局混亂而被迫嵌套布局的問題媒咳,解決權(quán)重百分比布局時LinearLayout的不足紫皇,并且提供特殊布局方式草丧,如圓形布局、特殊疊加擺放等轰绵。
學(xué)習(xí)本布局的目標(biāo)是實現(xiàn)不嵌套的復(fù)雜布局粉寞。
本系列學(xué)習(xí)心得,先講解基本用法左腔,然后逐步進行進階實戰(zhàn)UI效果的實現(xiàn)仁锯,采坑之路的心得等。

低版本用Compile翔悠,關(guān)鍵字业崖。高版本Android Studio如下

implementation 'com.android.support.constraint:constraint-layout:1.1.0'

如下圖方法數(shù)統(tǒng)計圖,所以對整個項目的包大小不構(gòu)成威脅蓄愁,可以放心食用双炕,入口有點甜。


image.png

目錄

  1. 基礎(chǔ)屬性介紹
  2. 相對擺放
  3. 水平居中以及權(quán)重居中
  4. Margin間距失效
  5. 目標(biāo)依賴約束對象隱身術(shù)
  6. 圓形布局
  7. 寬高約束
  8. Guideline
  9. 鏈?zhǔn)讲季?/li>
  10. 布局分組-控制可見性

基礎(chǔ)屬性介紹

大家應(yīng)該熟悉相對布局RelativeLayout撮抓,有很多belowOf妇斤,rightOf類似的屬性,用于做控件之間相對定位布局丹拯。所以開篇我們先講這個基礎(chǔ)屬性站超,如何在ConstraintLayout布局內(nèi),進行相對定位乖酬。

屬性名 簡介
layout_constraintLeft_toLeftOf 當(dāng)前控件A左側(cè)依賴于目標(biāo)約束對象B的左側(cè)死相,簡單點 就是A左靠近B左側(cè)對齊
layout_constraintLeft_toRightOf 當(dāng)前控件A左側(cè)依賴于目標(biāo)約束對象B的右側(cè),簡單點 就是A左靠近B右側(cè)對齊
layout_constraintRight_toLeftOf 當(dāng)前A右側(cè)靠近B左側(cè)對齊咬像,接下來的屬性類似...
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf 文本基準(zhǔn)線對齊
layout_constraintStart_toEndOf 當(dāng)前控件A起始邊與目標(biāo)約束對象B尾部對齊
layout_constraintStart_toStartOf 當(dāng)前控件A起始邊與目標(biāo)約束對象B起始邊對齊算撮,下面類似
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
image.png

如上所述生宛,常見的基本屬性就是這些,我們先學(xué)習(xí)這些近似相對布局的屬性肮柜。理解上述屬性的宗旨是陷舅,把當(dāng)前控件分為上下左右四個方向,在不同的情況下根據(jù)UI圖审洞,進行相對約束申明莱睁。

常用特性介紹

1. 相對擺放

下面2個控件Button1在父布局右上角,button2只申明在button1的下方芒澜。跟相對布局一樣缩赛,Android坐標(biāo)默認(rèn)是中心點在左上角,所以不申明水平約束撰糠,會默認(rèn)讓Button2在左側(cè)。

image.png
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/button1"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="我在右上角"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="我在他下面"
       app:layout_constraintTop_toBottomOf="@id/button1"/>


</android.support.constraint.ConstraintLayout>
2. 水平居中以及權(quán)重居中

下面開始進階使用辩昆,如何水平居中阅酪。在下圖中的ConstraintLayout下,Button控件就像是橡皮泥汁针,多重約束控制時术辐,會被拉伸。比如view的左側(cè)要貼住父布局左側(cè)施无,view的右側(cè)又要靠近父布局右側(cè)辉词,這樣view只好在中間開始被向兩邊拉伸。這個就跟你在媳婦和公婆之間糾結(jié)一樣猾骡,兩邊都要你表態(tài)瑞躺,哈哈。但是人是有私心的兴想,又要偏袒一方幢哨,或者一方一直處于劣勢,要維護下嫂便,所以又出現(xiàn)bias概念捞镰。如下圖,雖然是水平居中毙替,但是button2明顯偏向某一方岸售,0-1的權(quán)重值,越大就越靠近右側(cè)厂画。當(dāng)然你想玩得轉(zhuǎn)凸丸,設(shè)置0.5,兩邊不偏袒(我一條狗為啥說這個)袱院。這里說的是水平居中實現(xiàn)方式甲雅,至于垂直居中和父布局居中類似解孙,依樣畫葫蘆,自行實踐抛人。紅色的TextView展示如何平鋪填滿寬度弛姜,設(shè)置0dp(match_constraint )代表matchParent。

<?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">

    <Button
        android:id="@+id/button1"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="水平居中"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_marginTop="60dp"
        android:text="水平居中后偏向某一側(cè)"
        app:layout_constraintHorizontal_bias="0.6"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginTop="10dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="水平填滿"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button2"/>

</android.support.constraint.ConstraintLayout>
image.png
3. Margin間距失效

在這里要注意一點妖枚,ConstraintLayout布局中廷臼,我想讓Button2布局不遮擋演示的Button1,直接設(shè)置
android:layout_marginTop="60dp"是不行的绝页。如下圖荠商,沒有變更位置,控件依然遮擋Button1.

      <Button
        android:id="@+id/button2"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_marginTop="60dp"
        android:text="水平居中后偏向某一側(cè)"
        app:layout_constraintHorizontal_bias="0.6"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />
image.png

通過上面實踐發(fā)現(xiàn)续誉,沒有申明某一邊的約束目標(biāo)對象(比如這里是parent)莱没,設(shè)置對應(yīng)的邊的margin不起作用。比如我button1是有左側(cè)約束對象的酷鸦,此時設(shè)置300dp左間距饰躲,生效!

    <Button
        android:id="@+id/button1"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_marginLeft="300dp"
        android:text="水平居中"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
image.png
4. 目標(biāo)依賴約束對象隱身術(shù)

在UI實現(xiàn)中臼隔,有很多控件是在某一些場景下才會顯示嘹裂,但是布局肯定又得把它寫進去。然后顯示時摔握,它又要占據(jù)當(dāng)前常規(guī)情況下的控件的位置寄狼,需要調(diào)整這個常規(guī)控件向左或者向右移動位置。這種目標(biāo)隱身術(shù)氨淌,平常通過對這2個控件進行LinearLayout嵌套等方式去實現(xiàn)泊愧,很不好辦。下面介紹隱身術(shù)的應(yīng)對辦法,goneMargin大法盛正。

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

我在布局里拼卵,要求button1在最上面,button2和button3要相對button1在它下面蛮艰,當(dāng)button2顯示時腋腮,button3要在button2下面。此時就需要這樣布局了壤蚜。

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="你們跟著我"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_marginTop="100dp"
        android:text="我是2.我在他下面"
        android:visibility="visible"
        app:layout_constraintTop_toBottomOf="@id/button1"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="我是3.我在他下面"
        app:layout_constraintTop_toBottomOf="@id/button2"
        />
</android.support.constraint.ConstraintLayout>
image.png

接下來我再設(shè)置 android:visibility="gone"即寡,隱藏button2,神奇的一幕發(fā)生了袜刷。此時button2消失后聪富,button2的marginTop100dp也沒了,button3仍然保持button2之前對button1的依賴約束著蟹。

image.png

那么如果我還想要維持之前的100dp怎么辦墩蔓,設(shè)置button3的marginTop為100dp梢莽,不行,會變成下面圖的樣子奸披。


這個時候就請出goneMargin了昏名,如下圖。

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="你們跟著我"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_marginTop="100dp"
        android:text="我是2.我在他下面"
        android:visibility="visible"
        app:layout_constraintTop_toBottomOf="@id/button1"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="150dp"
        android:layout_height="50dp"
        app:layout_goneMarginTop="100dp"
        android:text="我是3.我在他下面"
        app:layout_constraintTop_toBottomOf="@id/button2"
        />
</android.support.constraint.ConstraintLayout>
image.png

設(shè)置button2消失后阵面,如下圖


image.png

OK轻局,一切如我們想要的效果一樣,完美样刷。那么如果我不需要在button2消失后仑扑,保持這么多間距呢,
app:layout_goneMarginTop改下即可置鼻,實際業(yè)務(wù)場景經(jīng)常有這種需要镇饮,上方的布局消失后,與頂部間距有不一樣的間距箕母,此時goneMargin就發(fā)揮大作用了储藐。不用自己代碼里搞事情去實現(xiàn)動態(tài)區(qū)分布局。

5. 圓形布局

實現(xiàn)星星環(huán)繞效果的布局司蔬,一看這個效果,開發(fā)頭都大了姨蝴,自定義layout group俊啼?不不不,我們有新的真愛來救我們了左医。圓形布局大法幫你實現(xiàn)各種吊炸天的設(shè)計效果圖授帕。另外也可實現(xiàn)頭像右上角角標(biāo)效果。

layout_constraintCircle :依賴哪個控件進行布局
layout_constraintCircleRadius :到依賴對象中心的距離
layout_constraintCircleAngle :當(dāng)前要擺放的控件應(yīng)處于哪個角度(度數(shù)浮梢,從0到360)
image.png

廢話不多說跛十,show you fuck code。

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">


    <Button
        android:id="@+id/button1"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:text="垂直居中"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:text="A"
        app:layout_constraintCircle="@+id/button1"
        app:layout_constraintCircleAngle="45"
        app:layout_constraintCircleRadius="70dp"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:text="B"
        app:layout_constraintCircle="@+id/button1"
        app:layout_constraintCircleAngle="90"
        app:layout_constraintCircleRadius="70dp"/>

    <Button
        android:id="@+id/button4"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:text="C"
        app:layout_constraintCircle="@+id/button1"
        app:layout_constraintCircleAngle="135"
        app:layout_constraintCircleRadius="70dp"/>
</android.support.constraint.ConstraintLayout>
image.png

上圖我們實現(xiàn)了A在45°方向擺放秕硝,并且靠近依賴約束的對象的中心點70dp芥映,B和C類似,跟A間隔45°擺放远豺,一種星星環(huán)繞效果實現(xiàn)好了奈偏。想想以前怎么實現(xiàn),是不是淚奔躯护。惊来。。組織上來拯救我們了棺滞,給google遞茶裁蚁,遞辣條矢渊!

6. 寬高約束

很多時候我們需要設(shè)置最大寬度和高度,或者最小寬度或高度枉证。那么在ConstraintLayout里矮男,我們將接觸多種限制手段。

屬性 簡介
layout_constraintWidth_min和layout_constraintHeight_min 設(shè)置寬高的最小值
layout_constraintWidth_max和layout_constraintHeight_max 設(shè)置寬高的最大值
layout_constraintWidth_percent和layout_constraintHeight_percent 設(shè)置寬高的比例值刽严,需要設(shè)置寬高layout_width昂灵、layout_height屬性為MATCH_CONSTRAINT(0dp)

除了上述屬性外,1.1版本開始新增加WRAP_CONTENT時的強制約束特性舞萄,下圖中眨补,由于WRAP_CONTENT時,寬高約束失效倒脓,第一個控件雖然申明了最大寬度撑螺,但是并沒有起作用。但是第二個控件 app:layout_constrainedWidth="true"設(shè)置后崎弃,寬度被限制在200dp甘晤。

//屬性
app:layout_constrainedWidth=”true|false”
app:layout_constrainedHeight=”true|false”

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:text="我的寬度被限制了,但是不起作用我的寬度被限制了,但是不起作用我的寬度被限制了,但是不起作用"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintWidth_max="200dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:maxWidth="100dp"
        android:text="寬度限制起作用了,寬度限制起作用了寬度限制起作用了寬度限制起作用了"
        app:layout_constrainedWidth="true"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button1"
        app:layout_constraintWidth_max="200dp"/>


</android.support.constraint.ConstraintLayout>

image.png

此外饲做,可以設(shè)置寬高的比例线婚,比如16:9.下圖文本顯示“111”控件是16:9的效果,"H,16:9"代表約束高度,且保持寬高比16:9盆均;根據(jù)上面的學(xué)習(xí)塞弊,寬度0dp時,設(shè)置了左邊和右邊的依賴約束對象為parent泪姨,所以寬度是已知的充滿屏幕游沿;利用已知的寬計算出 高度=寬度*16/9。
對于這一塊肮砾,我也是有很多疑問诀黍,還沒完全理解,等理解后仗处,再對ratio進行詳細解釋眯勾。下面這一句是別人貼出來的。

In this case the system sets the largest dimensions the satisfies all constraints and maintains the aspect ratio specified.

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/colorAccent"
        android:text="1111111"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:background="#cccccc"
        android:gravity="center"
        android:text="22222"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="W,1:4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <TextView
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="@color/colorPrimary"
        android:text="4444444"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="W,1:4"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />


    <TextView
        android:layout_width="0dp"
        android:layout_height="30dp"
        android:background="@color/colorPrimary"
        android:text="55555"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,1:4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <TextView
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:background="@color/colorPrimary"
        android:text="333333"
        app:layout_constraintHeight_percent="0.3"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

</android.support.constraint.ConstraintLayout>
image.png
7. Guideline

有些時候UI效果把界面化為幾個區(qū)域婆誓,A區(qū)域會根據(jù)B區(qū)域的寬度而動態(tài)調(diào)整位置咒精。或者有時候旷档,某些控件要作為一個整體在同一垂直方向都居中(這些控件在同一個X坐標(biāo))模叙,但是以前的相對布局單純設(shè)置垂直居中就會被疊加。比如下圖效果鞋屈,1和2控件都要在垂直居中范咨,使用Guideline可以愉快的解決這些問題故觅。其中的 app:layout_constraintGuide_percent="0.5"表示在垂直方向50%的位置。

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">


    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5"

        />

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorAccent"
        android:text="1111"
        app:layout_constraintBottom_toTopOf="@id/guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorPrimary"
        android:text="2222"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/guideline"/>

</android.support.constraint.ConstraintLayout>
8. 鏈?zhǔn)讲季?/h5>

當(dāng)AB控件相互之間建立依賴約束時渠啊,比如A申明右邊與B的左邊約束输吏,B同樣申明,形成一個回路替蛉,就產(chǎn)生了鏈AB贯溅。比如官網(wǎng)的下圖


image.png

image.png

其中第一個申明的控件作為鏈頭,所有鏈的屬性在鏈頭申明躲查,比如chainstyle它浅。根據(jù)官網(wǎng)的圖,chainstyle有下面幾種镣煮,默認(rèn)是spread姐霍。


image.png

重點講下權(quán)重鏈,類似于linearlayout的weight使用典唇,但是比它要更強大镊折。設(shè)置0dp(MATCH_CONSTRAINT)的鏈內(nèi)控件將瓜分剩余可用控件,根據(jù)權(quán)重值介衔,分割不同的大小恨胚。如下圖,Button1和button2設(shè)置了0dp,因為button1設(shè)置了做間距80dp炎咖,瓜分剩余空間是在這個區(qū)域右側(cè)赃泡。由于未設(shè)置具體權(quán)重,所以2者均分塘装。而button3急迂、button4影所、button5不一樣蹦肴,button5設(shè)置了50dp寬度,但是未設(shè)置權(quán)重猴娩,而butto3和button4分別設(shè)置了1阴幌、2的權(quán)重值,所以button4是button3的2倍大小卷中。


image.png
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <Button
        android:id="@+id/button1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="80dp"
        android:text="Button1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button2"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toRightOf="parent"/>


    <Button
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button4"/>

    <Button
        android:id="@+id/button4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button4"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintLeft_toRightOf="@+id/button3"
        app:layout_constraintRight_toLeftOf="@+id/button5"
        />

    <Button
        android:id="@+id/button5"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:text="Button5"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/button4"
        app:layout_constraintRight_toRightOf="parent"/>

</android.support.constraint.ConstraintLayout>


9. 布局分組-控制可見性

利用constraint.Group對布局里的控件進行分組矛双,app:constraint_referenced_ids里申明同一組的控件。
看源碼其實group類繼承ConstraintHelper蟆豫,最終繼承的view议忽。我們通過referenced_ids屬性設(shè)置的id數(shù)組最終被它存放,最終updatePreLayout方法遍歷設(shè)置可見或不可見等十减。比如下圖栈幸,我button1所在的group設(shè)置了invisible,button2保持了與button1的約束愤估。而左下角放置的2個button都因為group設(shè)置了gone,導(dǎo)致隱藏了速址。值得注意的是玩焰,一旦被設(shè)置到某個分組group控件里,子控件本身的visibility屬性就不起作用了芍锚,group設(shè)置的隱藏和可見才是最終的效果昔园,默認(rèn)group是顯示。


image.png
<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">

    <android.support.constraint.Group
        android:id="@+id/group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="invisible"
        app:constraint_referenced_ids="button1"/>

    <android.support.constraint.Group
        android:id="@+id/group2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:constraint_referenced_ids="button3,button4"/>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="80dp"
        android:text="Button1"
        android:visibility="gone"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button2"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toRightOf="parent"/>


    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        />


    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button4"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@id/button3"
        />
</android.support.constraint.ConstraintLayout>

而看源碼group并炮,像space控件一樣draw()為空默刚,沒有繪制動作,性能上沒有什么負擔(dān)渣触。在上面介紹的Guideline也是同樣如此羡棵,

    public void onDraw(Canvas canvas) {
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (this.mUseViewMeasure) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        } else {
            this.setMeasuredDimension(0, 0);
        }

    }
10. Barrier

如果A控件要同時在B和C的右側(cè),而B和C又長度不一定嗅钻,此時相對布局無法確定A到底寫誰右側(cè)好皂冰,而只能嵌套一個層,然后A在B和C的父布局右側(cè)养篓,這樣很不好秃流,所以Barrier界線就是拿來做這種特殊布局的。

<?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"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent">


    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="80dp"
        android:text="Button1-111111111111"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="80dp"
        android:text="Button2"
        app:layout_constraintLeft_toLeftOf="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"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Button3"
        app:layout_constraintLeft_toRightOf="@id/barrier"
        app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
image.png

下面是在具體實踐中的一種UI效果事例柳弄,僅供參考練習(xí)舶胀。整個布局只有一層,避免了嵌套過審的問題碧注∠ィ“張三”和下面的轉(zhuǎn)圈圖片以及“我放學(xué)了”文本提示都是要求作為一個整體垂直居中,如果常規(guī)的布局萍丐,需要把這三個放到一個容器里一起進行居中轩端,必然存在嵌套,但是約束布局就不需要這樣逝变。下面轉(zhuǎn)圈圖片消失時基茵,我放學(xué)文本提示要自動依賴顯示在左側(cè)方形圖片右側(cè),與張三左對齊壳影,傳統(tǒng)的布局也需要對我放學(xué)了文本和轉(zhuǎn)圈圖片進行嵌套拱层,這樣加上上面的嵌套,導(dǎo)致多了2層嵌套宴咧。


image.png
<?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="67dp"
    >

    <ImageView
        android:id="@+id/sdv_chat_dialog_header"
        android:layout_width="44dp"
        android:layout_height="44dp"
        android:layout_marginLeft="16dp"
        android:background="@null"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:src="@drawable/ic_launcher_background"
        app:layout_constraintTop_toTopOf="parent"
        />

    <TextView
        android:id="@+id/rrv_remind_unread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="34dp"
        android:gravity="center"
        android:includeFontPadding="false"
        android:textColor="#ff4444"
        app:layout_constraintLeft_toLeftOf="@id/sdv_chat_dialog_header"
        app:layout_constraintTop_toTopOf="@id/sdv_chat_dialog_header"
        tools:text="9"/>

    <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="sdv_chat_dialog_header"/>

    <android.support.constraint.Guideline
        android:id="@+id/guideline_horizontal_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5"
        />

    <TextView
        android:id="@+id/tv_chat_dialog_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="11dp"
        android:includeFontPadding="false"
        android:singleLine="true"
        android:textColor="#000000"
        android:textSize="17sp"
        app:layout_constraintBottom_toTopOf="@id/guideline_horizontal_center"
        app:layout_constraintLeft_toRightOf="@id/barrier"
        tools:text="張三"/>

    <TextView
        android:id="@+id/tv_chat_dialog_update_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="16dp"
        android:includeFontPadding="false"
        android:textSize="12sp"
        app:layout_constraintBaseline_toBaselineOf="@id/tv_chat_dialog_name"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="18:05"/>


    <ImageView
        android:id="@+id/iv_chat_watch_sync"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="11dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="2dp"
        android:background="@mipmap/ic_synchronization"
        android:visibility="visible"
        app:layout_constraintLeft_toRightOf="@id/barrier"
        app:layout_constraintTop_toBottomOf="@id/guideline_horizontal_center"
        />

    <TextView
        android:id="@+id/tv_chat_dialog_last_msg_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dp"
        android:includeFontPadding="false"
        android:singleLine="true"
        android:textColor="#000000"
        android:textSize="13sp"
        app:layout_constraintLeft_toRightOf="@id/iv_chat_watch_sync"
        app:layout_constraintRight_toLeftOf="@id/tv_chat_dialog_update_time"
        app:layout_constraintTop_toBottomOf="@id/guideline_horizontal_center"
        app:layout_goneMarginLeft="11dp"
        tools:text="我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了,我放學(xué)了8888888"/>


    <View
        android:id="@+id/view_divider"
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginLeft="72dp"
        android:background="#cccccc"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>

</android.support.constraint.ConstraintLayout>

結(jié)尾

約束布局也不是一定要完全替代傳統(tǒng)布局根灯,合適的才是最好的。充分利用各種布局的特性滿足UI效果,才是最好的編碼方式烙肺。
到這里芥驳,一些常見的使用已經(jīng)具備了,剩下的就是實戰(zhàn)磨合API茬高,還有一些進階配合使用下一次再講兆旬。
比如ConstraintSet,在代碼里動態(tài)改變約束怎栽,做一些布局動畫丽猬。代碼就不用貼出來,都在上面熏瞄。大家可以在拷貝后脚祟,不斷修改以便熟悉API。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末强饮,一起剝皮案震驚了整個濱河市由桌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌邮丰,老刑警劉巖行您,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剪廉,居然都是意外死亡娃循,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門斗蒋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捌斧,“玉大人,你說我怎么就攤上這事泉沾±搪欤” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵跷究,是天一觀的道長姓迅。 經(jīng)常有香客問我,道長揭朝,這世上最難降的妖魔是什么队贱? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任色冀,我火速辦了婚禮潭袱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锋恬。我一直安慰自己屯换,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彤悔,像睡著了一般嘉抓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晕窑,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天抑片,我揣著相機與錄音,去河邊找鬼杨赤。 笑死敞斋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疾牲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼把将!你這毒婦竟也來了舀患?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤舌剂,失蹤者是張志新(化名)和其女友劉穎济锄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霍转,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡拟淮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了谴忧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片很泊。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沾谓,靈堂內(nèi)的尸體忽然破棺而出委造,到底是詐尸還是另有隱情,我是刑警寧澤均驶,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布昏兆,位于F島的核電站,受9級特大地震影響妇穴,放射性物質(zhì)發(fā)生泄漏爬虱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一腾它、第九天 我趴在偏房一處隱蔽的房頂上張望跑筝。 院中可真熱鬧,春花似錦瞒滴、人聲如沸曲梗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虏两。三九已至愧旦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間定罢,已是汗流浹背笤虫。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祖凫,地道東北人耕皮。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像蝙场,于是被迫代替她去往敵國和親凌停。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容