ConstraintLayout布局出來(lái)已經(jīng)很久了,剛出來(lái)那會(huì)兒就想嘗試一下的,結(jié)果半天都沒(méi)適應(yīng),前兩天看到一篇ConstraintLayout實(shí)戰(zhàn)的文章,看完之后發(fā)現(xiàn)這布局賊雞兒好用啊,日常開(kāi)發(fā)中的大多數(shù)布局使用它都可以完成,而且也不需要嵌套。
介紹
ConstraintLayout又稱約束布局,是谷歌在2016年開(kāi)發(fā)者大會(huì)上推出的,之后在Android Studio上成為了默認(rèn)布局,該布局能減少布局的層級(jí)嵌套,我們都知道,View嵌套的越多,在加載的過(guò)程中解析起來(lái)就越費(fèi)時(shí)間,該布局幾乎能做到LinearLayout和RelativeLayout嵌套完成的任何布局,下面跟著一波小demo來(lái)深入了解谷歌推薦的ConstraintLayout。
用法簡(jiǎn)介
1、xxx_toyyyOf屬性
xxx是當(dāng)前的控件,yyy是指定控件,這個(gè)指定控件也可以是容器本身(parent)
ConstraintLayout中有以下多種這樣的屬性:
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

參照上圖給出的解釋,以上屬性都可以這樣用,有點(diǎn)類似RelativeLayout中的toLeftOf,toRightOf,上面的屬性中還有一個(gè)關(guān)于Baseline的,我們通過(guò)另外一張圖來(lái)了解一下:

Baseline是控件中文字的基準(zhǔn)線,這里可以理解為參照某個(gè)控件中的文字底部對(duì)齊,來(lái)看看樣式:

如果不加基準(zhǔn)線對(duì)齊的話,那么ButtonA的位置就在容器的左上角。
2、設(shè)置margin邊距
邊距,和傳統(tǒng)的布局是一樣的用法,但是這里要注意的是,必須要設(shè)置自己的相對(duì)位置(先要指定自己在容器中的位置,可以是相對(duì)容器的,也可以是相對(duì)某個(gè)控件的),如果不設(shè)置的話,那么設(shè)置margin是無(wú)效的,大家可以試試,在一個(gè)ConstraintLayout布局中放一個(gè)按鈕,除了邊距之外什么都不設(shè)置,這樣是沒(méi)有效果的,因?yàn)槟銢](méi)有在布局中給它設(shè)置相對(duì)位置。
3、隱藏空間設(shè)置邊距
ConstraintLayout中有以下多種這樣的屬性:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
平常我們?cè)陂_(kāi)發(fā)過(guò)程中會(huì)遇到這樣一個(gè)問(wèn)題,當(dāng)一個(gè)控件被設(shè)置成gone之后,與之關(guān)聯(lián)的控件的位置常常也會(huì)發(fā)生改變,來(lái)看看樣式:

平常我們寫(xiě)標(biāo)題欄的時(shí)候應(yīng)該都遇到過(guò)右邊放兩個(gè)按鈕的情況,而且是可以控制顯示隱藏的,當(dāng)最右邊的按鈕隱藏之后,左邊的按鈕也要距離右邊有一個(gè)邊距,這種情況下我們就可以使用上面這些屬性來(lái)配置布局。
4、居中和偏移
- 水平居中
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

這個(gè)很好理解,設(shè)置與容器的左邊和右邊分別對(duì)齊,這樣的話就能讓控件水平居中了,同理垂直居中和中心對(duì)齊也是這樣。可能有人會(huì)吐槽了,寫(xiě)這么多還不如我用LinearLayout和RelativeLayout寫(xiě)一句代碼來(lái)的快呢?老鐵還真是個(gè)急性子,接著往下看。
- 垂直居中
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
- 中心
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
下面來(lái)實(shí)現(xiàn)一個(gè)這樣的功能,讓一個(gè)控件在距離左邊和距離右邊的比例是1:3,來(lái)看看正經(jīng)寫(xiě)法:

<LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<Button
android:layout_width="100dp"
android:layout_height="match_parent" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
相信大多數(shù)老鐵都會(huì)這么寫(xiě),那么我們現(xiàn)在來(lái)看看不正經(jīng)的寫(xiě)法:
<android.support.constraint.ConstraintLayout>
<Button
android:id="@+id/button"
app:layout_constraintHorizontal_bias="0.33"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent />
</android.support.constraint.ConstraintLayout>
看到這個(gè)是不是驚呆了,一行代碼就搞定了,簡(jiǎn)直不要太簡(jiǎn)潔。
5、CircleRadius角度定位(在版本1.1中加入)

官網(wǎng)給出的解釋是,你可以以角度和距離約束窗口小部件中心相對(duì)于另一個(gè)窗口小部件中心??赡苡行┤丝床惶?,我也沒(méi)看懂(哈哈,LZ你是來(lái)搞笑的嗎),但是看官網(wǎng)給出的圖我大概明白是什么意思了,簡(jiǎn)單來(lái)說(shuō)就是可以根據(jù)兩個(gè)控件的中心來(lái)形成約束關(guān)系,然后可以通過(guò)設(shè)置角度來(lái)控制這個(gè)約束關(guān)系(還看不懂的話那就來(lái)實(shí)踐一把)

layout_constraintCircle表示相對(duì)某一指定控件,上圖中表示相對(duì)ButtonA;layout_constraintCircleRadius表示該控件的中心點(diǎn)到指定控件的中心點(diǎn)的距離(兩點(diǎn)之間,直線最短);layout_constraintCircleAngle表示該控件的中心點(diǎn)在指定控件垂直方向上的角度(范圍是0-360),具體看上圖中標(biāo)示的。
6、尺寸約束
在ConstraintLayout布局中,你可以設(shè)置布局的最大和最小尺寸,而且你可通過(guò)三種方式來(lái)設(shè)置控件的大小:
特定數(shù)值,比如123dp
使用
wrap_content,控件將自己計(jì)算大小使用0dp,相當(dāng)于
MATCH_CONSTRAINT
注意:match_parent官方不建議在ConstraintLayout布局中使用,可以通過(guò)設(shè)置MATCH_CONSTRAINT(真實(shí)數(shù)值是0dp)配合約束來(lái)定義布局
下面我們來(lái)看一個(gè)例子:

ButtonA是固定寬度且靠左,給ButtonB設(shè)置了約束,剛開(kāi)始預(yù)期的是設(shè)置ButtonB的寬度慢慢增大,超過(guò)ButtonA之后不管設(shè)置多大都像ButtonC和ButtonD一樣,但是ButtonA卻把ButtonB覆蓋了,顯然這不是我們需要的,這時(shí)候MATCH_CONSTRAINT的作用就能體現(xiàn)出來(lái)了,怎么理解這個(gè)MATCH_CONSTRAINT,我們可以理解成為了配合約束布局而代替了match_parent
7、設(shè)置寬高比例
在使用百分比布局時(shí),有兩種形式可以設(shè)置:
-
layout_constraintDimensionRatio,給寬或者高其中一個(gè)設(shè)置為0dp,然后設(shè)置該屬性是一個(gè)比例,寬和高的比(相對(duì)那個(gè)已知長(zhǎng)度的),可能說(shuō)的有點(diǎn)繞,下面我們直接看demo:

-
app:layout_constraintDimensionRatio,設(shè)置寬和高都為0dp,然后設(shè)置改屬性的值為H,x:y或者W,x:y,看一下demo

8、Chains(鏈)
鏈條在同一方向上(水平或者垂直)為一組互相關(guān)聯(lián)的控件作統(tǒng)一管理,并且鏈由鏈頭(鏈的第一個(gè)元素)設(shè)置的屬性控制,鏈頭是水平鏈的最左側(cè)的元素,是垂直鏈的最頂部的元素。我們來(lái)看看一些鏈的樣式:

我們只需要設(shè)置layout_constraintHorizontal_chainStyle或者layout_constraintVertical_chainStyle的屬性就好了,而這個(gè)屬性有以下幾種配置:
CHAIN_SPREAD模式:元素將展開(kāi)(默認(rèn)樣式)加權(quán)鏈
CHAIN_SPREAD模式:如果給元素的寬或者高設(shè)置了MATCH_CONSTRAINT(0dp),它們將分割寬高方向上的可用空間CHAIN_SPREAD_INSIDE模式:類似于SPREAD,但鏈的端點(diǎn)不會(huì)分散CHAIN_PACKED模式:鏈條的元素將被捆綁在一起。然后,子項(xiàng)的水平或垂直偏差屬性將影響該鏈元素的定位
9、輔助布局Guildline
這是ConstraintLayout布局特有的功能,你可以用它來(lái)輔助你完成布局,類似于高中數(shù)學(xué)圖形學(xué)中的輔助線,只不過(guò)這條輔助線只有兩個(gè)方向,水平和垂直:
當(dāng)設(shè)置線的方向?yàn)?code>horizontal時(shí),輔助線的高度為0,寬度是容器的寬度。
當(dāng)設(shè)置線的方向?yàn)?code>vertical時(shí),輔助線的寬度為0,高度時(shí)容器的高度。
我們來(lái)看看Guildline的樣式(需要注意的是,輔助線是不可見(jiàn)的,只有在預(yù)覽的時(shí)候才能通過(guò)鼠標(biāo)選中可見(jiàn)):

Guildline有三個(gè)常用的屬性,用來(lái)控制輔助線的位置:
layout_constraintGuide_begin:指定輔助線距離左邊或者頂部的距離layout_constraintGuide_end:指定輔助線距離右邊或者底部的距離layout_constraintGuide_percent:指定在父控件中的寬度或高度的百分比
代碼
以上demo的代碼全都上傳至ConstraintLayout最強(qiáng)布局解析,有興趣的童鞋可以自行下載看看