ConstraintLayout從入門到精通

1、介紹

在Android 開發(fā)最常用的是:線性布局LinearLayout和相對(duì)布局RelativeLayout,在使用的過(guò)程中都是各種嵌套,嚴(yán)重影響了代碼的可讀性。
約束布局ConstraintLayout的出現(xiàn)主要是為了解決布局嵌套過(guò)多的問(wèn)題,以靈活的方式定位和調(diào)整小部件。可以在Api9以上的Android系統(tǒng)使用它,從Android Studio 2.3起,官方的模板默認(rèn)使用ConstraintLayout。

2、如何使用ConstraintLayout

對(duì)于剛上手的童鞋,看著各種不習(xí)慣,等使用熟練以后就會(huì)發(fā)現(xiàn)它的各種好處了,代碼終于不用在像以前那樣嵌套到惡心的地步。廢話不多說(shuō),下面看看具體怎么用的。
當(dāng)然英語(yǔ)不錯(cuò)的也可以去讀讀官方文檔,介紹的還是很詳細(xì)的:ConstraintLayout官方文檔
(1)相對(duì)定位,我個(gè)人理解用法上和相對(duì)布局也差不多吧

圖一、B在A的右側(cè)
<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
        app:layout_constraintLeft_toRightOf="@+id/buttonA" />

約束條件如下:

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

這里的屬性對(duì)比上面的一個(gè)例子,相信大家都看的懂了,其中有一個(gè)比較特殊:
layout_constraintBaseline_toBaselineOf,指的是文本基線對(duì)齊

圖二、基線

(2)邊距,其實(shí)這個(gè)就沒(méi)什么好說(shuō)的了,和之前的相對(duì)布局和線下布局都一樣,然后就列舉一下吧!

android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

(3)goneMargin,主要用于約束的控件可見(jiàn)性被設(shè)置為gone的時(shí)候使用的margin值,這個(gè)就比較人性化了,雖然不是很常用,但是用起來(lái)確實(shí)方便太多了,具體屬性如下:

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

舉個(gè)栗子:如果Button2的左面約束在Button1的右面,Button1設(shè)有10dp的左邊距,Button2沒(méi)有左邊距,但是給Button2設(shè)置10dp的goneMarginStart,現(xiàn)在把Button1可見(jiàn)性設(shè)置為GONE,就會(huì)如下圖顯示Button2會(huì)有10dp的左邊距。

圖三

(4)居中和偏移

<android.support.constraint.ConstraintLayout ...>
             <Button android:id="@+id/button" ...
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent/>
         </>

這里是左右居中,上下居中也同理。

圖四、居中樣式

然后就是偏移,可以設(shè)置邊距同樣也能達(dá)到偏移的效果,這個(gè)也是大家都知道的,所以再多介紹也沒(méi)什么意義,這里要介紹的是另外兩個(gè)新的屬性:

layout_constraintHorizontal_bias
layout_constraintVertical_bias

例如,下面將使左側(cè)具有30%的偏移而不是默認(rèn)的50%,這樣左側(cè)將更短,小部件將更傾向于左側(cè)。上下偏移這里就不再舉例介紹了。

<android.support.constraint.ConstraintLayout ...>
             <Button android:id="@+id/button" ...
                 app:layout_constraintHorizontal_bias="0.3"
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent/>
         </>
圖五、左右偏移樣式

(5)圓形定位,這個(gè)就顯得就比較高端了,雖然感覺(jué)用到的地方不是很多,但就是感覺(jué)很吊的樣子??梢砸砸粋€(gè)角度和一個(gè)距離約束一個(gè)小部件中心相對(duì)于另一個(gè)小部件中心。這允許您在一個(gè)圓上定位一個(gè)小部件??梢允褂靡韵聦傩裕?/p>

layout_constraintCircle : 引用另一個(gè)小部件ID
layout_constraintCircleRadius : 到其他窗口小部件中心的距離
layout_constraintCircleAngle : 小部件應(yīng)該處于哪個(gè)角度(度,從0到360)
圖六、圓形定位
<Button android:id="@+id/buttonA" ... />
  <Button android:id="@+id/buttonB" ...
      app:layout_constraintCircle="@+id/buttonA"
      app:layout_constraintCircleRadius="100dp"
      app:layout_constraintCircleAngle="45" />

(6)可見(jiàn)性行為,其實(shí)就是View.GONE,和之前的一樣,需要注意的就是當(dāng)有控件設(shè)置了goneMargin時(shí)的情況,這個(gè)上面有說(shuō)過(guò)。
(7)限制尺寸,約束布局的最小或最大尺寸,可以為約束布局本身定義最小和最大大小,一般設(shè)置寬度使用WRAP_CONTENT :

android:minwidth 設(shè)置布局的最小寬度
android:minheight 設(shè)置布局的最小高度
android:maxwidth 設(shè)置布局的最大寬度
android:maxheight 設(shè)置布局的最大高度

當(dāng)ConstraintLayout為1.1版本以下時(shí),使用以上屬性需要設(shè)置:

app:layout_constrainedWidth=”true|false”
app:layout_constrainedHeight=”true|false”

官方不推薦使用MATCH_CONSTRAINT,建議使用0dp去代替

圖七

a、是包裹內(nèi)容,b、設(shè)置了0dp,c、設(shè)置了0dp并設(shè)置了左邊距
下面是c的例子代碼:

<TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="50dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

在約束布局中寬高的維度 match_parent 被 0dp 代替,默認(rèn)生成的大小占所有的可用空間。那么有以下幾個(gè)屬性可以使用:
layout_constraintWidth_min and layout_constraintHeight_min //設(shè)置最小尺寸
layout_constraintWidth_max and layout_constraintHeight_max //設(shè)置最大尺寸
layout_constraintWidth_percent and layout_constraintHeight_percent //設(shè)置相對(duì)于父類的百分比
(8)寬高比,當(dāng)寬或高至少有一個(gè)尺寸被設(shè)置為0dp時(shí),可以通過(guò)屬性layout_constraintDimensionRatio設(shè)置寬高比。

<Button android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1" />

在設(shè)置寬高比的值的時(shí)候,還可以在前面加W或H,分別指定寬度或高度限制。

<Button android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="H,16:9"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

app:layout_constraintDimensionRatio="H,16:9"指的是 高:寬=16:9
app:layout_constraintDimensionRatio="W,16:9"指的是 寬:高=16:9

(9)鏈,如果兩個(gè)或以上控件通過(guò)下圖的方式約束在一起,就可以認(rèn)為是他們是一條鏈(圖為橫向的鏈,縱向同理)。

圖八、最小鏈

鏈頭,鏈由鏈的第一個(gè)元素(鏈的“頭”)上設(shè)置的屬性控制:

圖九、鏈頭
    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/TextView2" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_constraintRight_toLeftOf="@+id/TextView3" />

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/TextView2"
        app:layout_constraintRight_toRightOf="parent" />

在鏈的第一個(gè)元素上設(shè)置屬性layout_constrainthorizontal_chain style或layout_constraintvertical_chainstyle時(shí),鏈的行為將根據(jù)指定的樣式更改(默認(rèn)為chain_spread)。
1、CHAIN_SPREAD — 元素將展開(默認(rèn)樣式)
2、CHAIN_SPREAD_INSIDE —— 展開元素,但鏈的兩端貼近parent;
3、通過(guò)layout_constrainthorizontal_weight屬性設(shè)置了權(quán)重
4、CHAIN_PACKED —— 鏈的元素將被打包在一起。
5、如果設(shè)置了邊距,排列鏈的時(shí)候?qū)目偟姆峙涞目臻g中扣除。

圖十、鏈的樣式

3、輔助工具

1、Optimizer優(yōu)化器
在1.1中,我們公開了約束優(yōu)化器??梢酝ㄟ^(guò)將layout-optimizationlevel添加到constraintlayout元素來(lái)決定應(yīng)用哪些優(yōu)化。
none:無(wú)優(yōu)化
standard:默認(rèn)。僅優(yōu)化直接約束和屏障約束
direct:優(yōu)化直接約束
barrier:優(yōu)化屏障約束
chain:優(yōu)化鏈約束(實(shí)驗(yàn))
dimensions:優(yōu)化尺寸測(cè)量,減少匹配約束元素的測(cè)量數(shù)
2、Barrier

圖十一

假設(shè)有3個(gè)控件ABC,C在AB的右邊,但是AB的寬是不固定的,這個(gè)時(shí)候C無(wú)論約束在A的右邊或者B的右邊都不對(duì)。當(dāng)出現(xiàn)這種情況可以用Barrier來(lái)解決。Barrier可以在多個(gè)控件的一側(cè)建立一個(gè)屏障,如下所示:

圖十二

這個(gè)時(shí)候C只要約束在Barrier的右邊就可以了,代碼如下:

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/TextView1" />

    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="TextView1,TextView2" />

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/barrier" />

app:barrierDirection為屏障所在的位置,可設(shè)置的值有:bottom、end、left、right、start、top
app:constraint_referenced_ids為屏障引用的控件,可設(shè)置多個(gè)(用“,”隔開)
3、Group
Group可以把多個(gè)控件歸為一組,方便隱藏或顯示一組控件,舉個(gè)例子:

<TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/TextView1" />

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@id/TextView2" />

    <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="TextView1,TextView3" />

用Group把TextView1和TextView3歸為一組,再設(shè)置這組控件的可見(jiàn)性
4、Placeholder
Placeholder指的是占位符。在Placeholder中可使用setContent()設(shè)置另一個(gè)控件的id,使這個(gè)控件移動(dòng)到占位符的位置。舉個(gè)例子:

<android.support.constraint.Placeholder
        android:id="@+id/placeholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:content="@+id/textview"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#cccccc"
        android:padding="16dp"
        android:text="TextView"
        android:textColor="#000000"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

新建一個(gè)Placeholder約束在屏幕的左上角,新建一個(gè)TextView約束在屏幕的右上角,在Placeholder中設(shè)置 app:content="@+id/textview",這時(shí)TextView會(huì)跑到屏幕的左上角。效果如下:
5、Guideline
Guildline像輔助線一樣,在預(yù)覽的時(shí)候幫助你完成布局(不會(huì)顯示在界面上)。
Guildline的主要屬性:
android:orientation 垂直vertical,水平horizontal
layout_constraintGuide_begin 開始位置
layout_constraintGuide_end 結(jié)束位置
layout_constraintGuide_percent 距離頂部的百分比(orientation = horizontal時(shí)則為距離左邊)
舉個(gè)例子:

   <android.support.constraint.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="50dp" />

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

guideline1為水平輔助線,開始位置是距離頂部50dp,guideline2位垂直輔助線,開始位置為屏幕寬的0.5(中點(diǎn)位置),效果如下:


圖十三

4、總結(jié)

本篇文章主要介紹了ConstraintLayout的用法,剛開始可能會(huì)感覺(jué)到用的各種不習(xí)慣,用著用著就習(xí)慣了。ConstraintLayout的初衷是為了實(shí)現(xiàn)托拉拽完成布局,但本人還是比較喜歡直接用代碼寫,所以才專門研究一下,純粹個(gè)人喜好問(wèn)題,至于拖拽大家自己研究了。

?著作權(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)容