ConstraintLayout

網(wǎng)傳constraintLayout(約束布局)的布局,性能和功能性相當(dāng)優(yōu)越撩匕,雖然RelativeLayout用的飛起來蜂嗽,也得與時(shí)俱進(jìn)。

本文主要分為以下幾個(gè)部分:

catalog.png

1. 背景介紹

在面試的時(shí)候經(jīng)常會(huì)被問到有沒有做過布局優(yōu)化博其,都通過什么方式優(yōu)化布局界面的套才?優(yōu)化布局界面其中一種方式就是通過 ConstraintLayout 降低布局層級(jí),從而避免過度測(cè)量和繪制慕淡。本篇文章重點(diǎn)講解 ConstraintLayout 的用法背伴,關(guān)于 ConstraintLayout 性能方面的優(yōu)勢(shì),可以參考這篇文章:解析 ConstraintLayout 的性能優(yōu)勢(shì)峰髓。

通過可視化拖拽的方式編寫 ConstraintLayout 布局界面傻寂,個(gè)人是不太推崇的,雖然它確實(shí)很方便携兵,但是即使通過可視化拖拽的方式編寫布局之后疾掰,還是需要看懂 xml 文件中關(guān)于 ConstraintLayout 的屬性,才可以更靈活的修改布局界面徐紧,所以本文主要講解通過 xml 屬性的方式編寫 ConstraintLayout 布局界面静檬,關(guān)于可視化拖拽的方式編寫 ConstraintLayout 布局界面,可以參考郭霖寫的這篇博客: Android 新特性介紹浪汪,ConstraintLayout 完全解析

好了巴柿,上面介紹了 ConstraintLayout 的兩個(gè)優(yōu)點(diǎn),下面開始進(jìn)入本文的正題死遭,通過 xml 布局屬性的方式編寫 ConstraintLayout 布局。使用之前凯旋,需要在build.gradle文件中添加對(duì) ConstraintLayout 的依賴:

dependencies {? ? ...? ? implementation'com.android.support.constraint:constraint-layout:1.0.2'...}

2. 詳細(xì)使用

本節(jié)主要分為 7 點(diǎn)介紹 ConstraintLayout 的詳細(xì)使用呀潭,那就開始吧~

2.1 相對(duì)位置

ConstraintLayout 和 RelativeLayout 是非常類似的布局控件,它們之間最大的相似之處在于都可以編寫一個(gè)控件相對(duì)于其他控件或父控件的相對(duì)位置至非,比如下面這個(gè)樣式的布局既可以通過

RelativeLayout 實(shí)現(xiàn)钠署,也可以通過 ConstraintLayout 實(shí)現(xiàn)

relativepositioning.png

通過 ConstraintLayout 實(shí)現(xiàn)的代碼如下所示:

通過上面的代碼,可以看到幾個(gè)陌生的 xml 屬性荒椭,它們都是 ConstraintLayout 的 xml 屬性谐鼎,比如:

通過屬性的名字就可以猜測(cè)出它們大概的意思,比如:

app:layout_constraintLeft_toLeftOf是指該控件的左邊緣和某個(gè)控件的左邊緣對(duì)齊

app:layout_constraintRight_toRightOf是指該控件的右邊緣和某個(gè)控件的右邊緣對(duì)齊

app:layout_constraintTop_toBottomOf是指該控件的上邊緣和某個(gè)控件的下邊緣對(duì)齊

依次類推趣惠,同樣含義的屬性還有:

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_constraintStart_toEndOf

layout_constraintStart_toStartOf

layout_constraintEnd_toStartOf

layout_constraintEnd_toEndOf

layout_constraintBaseline_toBaselineOf

上述屬性的屬性值可以是某個(gè)控件的 id狸棍,也可以是parent身害,比如:

app:layout_constraintLeft_toRightOf="@+id/tv_a"

app:layout_constraintRight_toRightOf="parent"

對(duì)于相對(duì)位置,官方給出的示意圖如下所示:

relativepositioning1.png

2.2 邊距(Margins)

假如現(xiàn)在有如下這樣一個(gè)界面:TextViewA 上邊距離 Toolbar 30dp草戈,在屏幕最左邊塌鸯,TextViewB 上邊距離 Toolbar 30dp,左邊距離 TextView A 也是 30dp唐片,該如何編寫布局文件呢丙猬?

margin.png

該布局 xml 關(guān)鍵代碼如下所示:

在 ConstraintLayout 布局中,下面幾個(gè) Margin 相關(guān)的屬性依然是有效的

android:layout_marginStart

android:layout_marginEnd

android:layout_marginLeft

android:layout_marginTop

android:layout_marginRight

android:layout_marginBottom

注意:在 ConstraintLayout 中费韭,上述屬性值只可以是正數(shù)或者0茧球,不可以是負(fù)數(shù)。

假如現(xiàn)在有這樣的一個(gè)需求星持,當(dāng) TextViewA 顯示的時(shí)候抢埋,TextViewB 距離左邊是 20dp;當(dāng) TextViewA 可見性為Gone的時(shí)候钉汗,TextViewB 距離左邊是 30dp羹令,使用 ConstraintLayout 可以很容易的實(shí)現(xiàn)這樣的需求。

在 ConstraintLayout 中如下這些邊距屬性就是當(dāng)依據(jù)的控件變?yōu)?Gone 的時(shí)候就會(huì)生效

layout_goneMarginStart

layout_goneMarginEnd

layout_goneMarginLeft

layout_goneMarginTop

layout_goneMarginRight

layout_goneMarginBottom

2.3 居中顯示

假如說有如下圖所示的一個(gè)界面损痰,TextViewA 在布局的正中間福侈,如果用 RelativeLayout 和 LinearLayout 實(shí)現(xiàn)是很方便的,但是用 ConstraintLayout 怎么實(shí)現(xiàn)呢卢未?

centerposition.png

其實(shí)也很簡單肪凛,代碼如下:

在 ConstraintLayout 中并不像 LinearLayout 和 RelativeLayout 是通過android:gravity="center"、android:layout_gravity="center"辽社、android:layout_centerVertical="true"和android:layout_centerHorizontal="true"設(shè)置居中位置的伟墙,而是通過app:layout_constraintBottom_toBottomOf、app:layout_constraintLeft_toLeftOf滴铅、app:layout_constraintRight_toRightOf和app:layout_constraintTop_toBottomOf設(shè)置該控件上下左右分別依附于指定的控件即可戳葵。

在 ConstraintLayout 中有一個(gè)非常重要的概念 ---- constraint(約束):當(dāng)控件有自己的大小時(shí),例如:wrap_content和具體的數(shù)值時(shí)汉匙,我們?yōu)榭丶砑拥亩际?constraint (約束)拱烁,這個(gè)約束有點(diǎn)像橡皮筋一樣會(huì)有一個(gè)拉力拉著控件,但是并不會(huì)改變控件的大小噩翠。

例如上例戏自,在居中顯示中,TextViewA 寬度為 100dp伤锚,左邊有app:layout_constraintLeft_toLeftOf="parent"約束擅笔,右邊有app:layout_constraintRight_toRightOf="parent"約束,左邊和右邊分別有一個(gè)同樣大小的力拉著 TextViewA 控件,所以 TextViewA 會(huì)水平居中猛们,豎直方向也是一樣的念脯。

如果想讓上述例子中的 TextViewA 水平方向撐滿整個(gè)父控件,即如下圖所示阅懦,那該怎么做呢和二?

centerposition1.png

首先我們想到的是使用android:layout_width="match_parent"實(shí)現(xiàn),這樣設(shè)置之后確實(shí)也會(huì)實(shí)現(xiàn)這樣的效果耳胎,但是查看 ConstraintLayout 的官方文檔發(fā)現(xiàn)惯吕,在 ConstraintLayout 中match_parent已經(jīng)被match_constraint所取代,所以使用android:layout_width="0dp"更為合適(在 xml 中并沒有match_constraint這個(gè)屬性值怕午,0dp 即代碼match_constraint值)废登。

Bias屬性

可以在上下和左右分別有約束的時(shí)候加上偏移率,屬性如下所示:

app:layout_constraintHorizontal_bias="0.1"

app:layout_constraintVertical_bias="0.8"

layout_constraintHorizontal_bias取值范圍是[0.0 ~ 1.0]郁惜,從左向右

layout_constraintVertical_bias取值范圍是[0.0 ~ 1.0]堡距,從上到下

centerposition2.png

2.4 可見性對(duì)布局的影響

在 2.1 節(jié)中提到過幾個(gè)特殊的屬性:

layout_goneMarginStart

layout_goneMarginEnd

layout_goneMarginLeft

layout_goneMarginTop

layout_goneMarginRight

layout_goneMarginBottom

這些屬性是配合著layout_marginStart等屬性使用的,當(dāng)控件的約束所依附的 target 控件的 visibility 不為 GONE 的時(shí)候兆蕉,layout_marginStart等屬性起作用羽戒,當(dāng) target 控件的 visibility 為 GONE 的時(shí)候,layout_goneMarginStart屬性起作用

2.5 尺寸約束

ConstraintLayout 的最小尺寸

當(dāng) ConstraintLayout 的寬度或者高度為wrap_content時(shí)虎韵,可以通過如下屬性為ConstraintLayout設(shè)置最小尺寸或最大尺寸

android:minWidth:最小寬度

android:minHeight:最小高度

android:maxWidth:最大寬度

android:maxHeight:最大高度

控件的尺寸約束

在ConstraintLayout中易稠,設(shè)置控件的大小總共有三種方式,分別是:

一個(gè)具體的屬性值包蓝,比如:123dp或者一個(gè) Dimension 引用

使用wrap_content驶社,根據(jù)自身大小決定

0dp即match_constraint

控件按寬高比設(shè)置大小

在ConstraintLayout中,其中的控件可以按照寬高比設(shè)置其大小测萎,前提是控件的寬或者高的尺寸至少有一個(gè)是0dp亡电,然后通過layout_constraintDimensionRatio設(shè)置控件的寬高比,顯示出來的控件的寬和高即是設(shè)置的比例的大小硅瞧,如下所示:

在上面 xml 代碼中份乒,Button 的寬度是一個(gè)特定值:wrap_content,高度是一個(gè)可變值:0dp腕唧,寬:高 = 1 :1冒嫡,則高度也就是和寬度相同的值

通過layout_constraintDimensionRatio設(shè)置的參數(shù)可以是:

一個(gè)浮點(diǎn)數(shù),代表寬/高的比例

也可以是上述例子中的形式:寬:高

當(dāng)控件寬和高的值都是0dp時(shí)四苇,也可以通過layout_constraintDimensionRatio設(shè)置寬和高的比例,比如:

在上面 xml 代碼中方咆,Button 的寬是可變值:0dp月腋,高也是可變值:0dp,高:寬 = 16:9,但是 Button 有上下兩個(gè)約束:高頂?shù)礁缚丶纳线吘売苌В醉數(shù)礁缚丶南逻吘壠模@樣 Button 的高度就固定了,再通過比例妓肢,即可得到寬 = 高 * 9/16.

2.5 鏈(Chains)

在 ConstraintLayout 中有一個(gè)非常重要的概念:鏈(Chains)

那什么才是鏈呢捌省?在下圖所示的界面中即存在一個(gè)鏈:

chains.png

上圖中 TextViewA、TextViewB 和 TextViewC 形成了一個(gè)鏈碉钠,上圖對(duì)應(yīng)的 xml 代碼是:

從代碼中可以看到形成鏈的三個(gè)控件有以下特點(diǎn):

TextViewA 和 TextViewB 通過app:layout_constraintRight_toLeftOf="@+id/tv_b"和app:layout_constraintLeft_toRightOf="@+id/tv_a"相互依賴

TextViewB 和 TextViewC 通過app:layout_constraintRight_toLeftOf="@+id/tv_c"和app:layout_constraintLeft_toRightOf="@+id/tv_b"相互依賴

這樣便形成了一個(gè)鏈纲缓,在此鏈中最左邊的控件稱為鏈頭。同樣的也可以通過上下相互依賴形成上下的鏈喊废,最上面的控件稱為鏈頭祝高。

在鏈頭中通過layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle可以設(shè)置鏈的樣式。

鏈的樣式總共有三種:

CHAIN_SPREAD:默認(rèn)樣式

CHAIN_SPREAD_INSIDE

CHAIN_PACKED

用一張官方的圖解釋上面幾個(gè)屬性的含義污筷,如下圖所示:

chainsStyle.png

這里需要強(qiáng)調(diào)下比重鏈(Weighted chain)樣式:在CHAIN_SPREAD樣式的鏈中工闺,如果其中的控件的寬度或高度為 0dp,即可以通過layout_constraintHorizontal_weight或layout_constraintVertical_weight設(shè)置該控件在水平或者豎直方向的比例瓣蛀,類似于 LinearLayout 中的 weight 屬性的作用

2.6 Guideline

在 ConstraintLayout 中有一個(gè)特殊的輔助類:android.support.constraint.Guideline陆蟆,主要用于輔助布局,可以把它看做是一個(gè)輔助線惋增,但是不會(huì)繪制到界面上叠殷,有水平的和垂直的。

Guideline有以下幾個(gè)屬性:

android:orientation:vertical或horizontal器腋,表示此 Guideline 是水平的還是垂直的

app:layout_constraintGuide_begin:表示 Guideline 的距離左邊或上邊的距離溪猿,根據(jù)方向決定是距離哪邊的

app:layout_constraintGuide_begin:表示 Guideline 的距離右邊或下邊的距離,根據(jù)方向決定是距離哪邊的

app:layout_constraintGuide_percent:表示 Guideline 距離左邊或上邊的百分比纫塌,根據(jù)方向決定是距離哪邊的

用一張效果圖展示 Guideline 的作用诊县,一個(gè) TextView 在中線的左邊 32dp 位置處,另一個(gè) TextView 在中線右邊 32dp 處

guideline.png

上圖代碼如下:

好啦措左,至此關(guān)于 ConstraintLayout 的使用就基本全部介紹完畢依痊,是不是覺得很好用呢?那就趕快在項(xiàng)目中使用起來的怎披!文中涉及的代碼都在這兒:ConstraintLayoutPractic胸嘁。

參考資料:

ConstraintLayout 官方文檔

ConstraintLayout 完全解析 快來優(yōu)化你的布局吧--Hongyang

Android ConstraintLayout 約束布局--打魚還是曬網(wǎng) —— stone

ConstraintLayout約束布局使用教程難點(diǎn)理解--yueding


鏈接:http://www.reibang.com/p/6e5fa646ddf5

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凉逛,隨后出現(xiàn)的幾起案子性宏,更是在濱河造成了極大的恐慌,老刑警劉巖状飞,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毫胜,死亡現(xiàn)場(chǎng)離奇詭異书斜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)酵使,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門荐吉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人口渔,你說我怎么就攤上這事样屠。” “怎么了缺脉?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵痪欲,是天一觀的道長。 經(jīng)常有香客問我枪向,道長勤揩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任秘蛔,我火速辦了婚禮陨亡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘深员。我一直安慰自己负蠕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布倦畅。 她就那樣靜靜地躺著遮糖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叠赐。 梳的紋絲不亂的頭發(fā)上欲账,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音芭概,去河邊找鬼赛不。 笑死,一個(gè)胖子當(dāng)著我的面吹牛罢洲,可吹牛的內(nèi)容都是我干的踢故。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼惹苗,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼殿较!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起桩蓉,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤淋纲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后院究,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帚戳,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玷或,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了片任。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔬胯,死狀恐怖对供,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氛濒,我是刑警寧澤产场,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站舞竿,受9級(jí)特大地震影響京景,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骗奖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一确徙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧执桌,春花似錦鄙皇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膘壶,卻和暖如春错蝴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颓芭。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工顷锰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畜伐。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓馍惹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玛界。 傳聞我的和親對(duì)象是個(gè)殘疾皇子万矾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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