最全面的ConstraintLayout教程
原創(chuàng)微信公眾號(hào)郭霖 WeChat ID: guolin_blog
本篇文章的主題是ConstraintLayout。其實(shí)ConstraintLayout是Android Studio 2.2中主要的新增功能之一擎淤,也是Google在去年的I/O大會(huì)上重點(diǎn)宣傳的一個(gè)功能廉侧。我們都知道持灰,在傳統(tǒng)的Android開(kāi)發(fā)當(dāng)中兑障,界面基本都是靠編寫(xiě)XML代碼完成的榆骚,雖然Android Studio也支持可視化的方式來(lái)編寫(xiě)界面鲤竹,但是操作起來(lái)并不方便浪读,我也一直都不推薦使用可視化的方式來(lái)編寫(xiě)Android應(yīng)用程序的界面。
而ConstraintLayout就是為了解決這一現(xiàn)狀而出現(xiàn)的辛藻。它和傳統(tǒng)編寫(xiě)界面的方式恰恰相反碘橘,ConstraintLayout非常適合使用可視化的方式來(lái)編寫(xiě)界面,但并不太適合使用XML的方式來(lái)進(jìn)行編寫(xiě)吱肌。當(dāng)然痘拆,可視化操作的背后仍然還是使用的XML代碼來(lái)實(shí)現(xiàn)的,只不過(guò)這些代碼是由Android Studio根據(jù)我們的操作自動(dòng)生成的氮墨。
另外纺蛆,ConstraintLayout還有一個(gè)優(yōu)點(diǎn),它可以有效地解決布局嵌套過(guò)多的問(wèn)題规揪。我們平時(shí)編寫(xiě)界面桥氏,復(fù)雜的布局總會(huì)伴隨著多層的嵌套,而嵌套越多猛铅,程序的性能也就越差字支。ConstraintLayout則是使用約束的方式來(lái)指定各個(gè)控件的位置和關(guān)系的,它有點(diǎn)類(lèi)似于RelativeLayout,但遠(yuǎn)比RelativeLayout要更強(qiáng)大堕伪。
其實(shí)ConstraintLayout屬于Android Studio 2.2的新特性揖庄,我在去年寫(xiě)《第二行代碼》的時(shí)候就非常想要將這部分內(nèi)容加入到新書(shū)里面,但是在嘗試之后還是放棄了欠雌。因?yàn)镃onstraintLayout的用法很多都是對(duì)控件進(jìn)行拖拽蹄梢,只用文字或者是一些靜態(tài)圖片實(shí)在太難將它的用法表達(dá)清楚了,因此不太適合寫(xiě)到書(shū)上富俄。我當(dāng)時(shí)的想法就是后面寫(xiě)一篇文章來(lái)講解ConstraintLayout的用法禁炒,彌補(bǔ)一下《第二行代碼》中缺失的這部分新特性,那么今天這篇文章來(lái)了蛙酪。
開(kāi)始
下面我們開(kāi)始用邊學(xué)邊練的方式來(lái)進(jìn)行學(xué)習(xí)齐苛,首先打開(kāi)你的Android Studio翘盖,并新建一個(gè)ConstraintLayoutTest項(xiàng)目。另外,確保你的Android Studio是2.2或以上版本踊跟。
為了要使用ConstraintLayout群井,我們需要在app/build.gradle文件中添加ConstraintLayout的依賴(lài),如下所示汰瘫。
目前ConstraintLayout庫(kù)最新的版本是1.0.0-beta4狂打,還沒(méi)有推出正式穩(wěn)定版本,不過(guò)這并不影響我們提前進(jìn)行學(xué)習(xí)和使用混弥。
現(xiàn)在打開(kāi)res/layout/activity_main.xml文件趴乡,由于這是一個(gè)新建的空項(xiàng)目,Android Studio會(huì)自動(dòng)幫我們創(chuàng)建好一個(gè)布局蝗拿,如下圖所示晾捏。
不過(guò),Android Studio自動(dòng)創(chuàng)建的這個(gè)布局默認(rèn)使用的是RelativeLayout哀托,我們可以通過(guò)如下操作將它轉(zhuǎn)換成ConstraintLayout惦辛。
轉(zhuǎn)換完成之后,原RelativeLayout中的內(nèi)容也會(huì)自動(dòng)轉(zhuǎn)換到ConstraintLayout中仓手,比如圖中的TextView胖齐。如果你不需要它的話,可以選中這個(gè)控件嗽冒,然后按鍵盤(pán)上的Delete鍵即可刪除呀伙。
我們可以看到,現(xiàn)在主操作區(qū)域內(nèi)有兩個(gè)類(lèi)似于手機(jī)屏幕的界面添坊,左邊的是預(yù)覽界面剿另,右邊的是藍(lán)圖界面。這兩部分都可以用于進(jìn)行布局編輯工作,區(qū)別是左邊部分主要用于預(yù)覽最終的界面效果驰弄,右邊部分主要用于觀察界面內(nèi)各個(gè)控件的約束情況麻汰。
基本操作
下面我們來(lái)學(xué)習(xí)一些具體的操作吧,ConstraintLayout的基本用法很簡(jiǎn)單戚篙,比如我們想要向布局中添加一個(gè)按鈕五鲫,那么只需要從左側(cè)的Palette區(qū)域拖一個(gè)Button進(jìn)去就可以了,如下圖所示岔擂。
雖說(shuō)現(xiàn)在Button已經(jīng)添加到界面上了位喂,但是由于我們還沒(méi)有給Button添加任何的約束,因此Button并不知道自己應(yīng)該出現(xiàn)在什么位置÷伊椋現(xiàn)在我們?cè)陬A(yù)覽界面上看到的Button位置并不是它最終運(yùn)行后的實(shí)際位置塑崖,如果一個(gè)控件沒(méi)有添加任何約束的話,它在運(yùn)行之后會(huì)自動(dòng)位于界面的左上角痛倚。
那么下面我們就來(lái)給Button添加約束规婆,每個(gè)控件的約束都分為垂直和水平兩類(lèi),一共可以在四個(gè)方向上給控件添加約束蝉稳,如下圖所示抒蚜。
上圖中Button的上下左右各有一個(gè)圓圈,這圓圈就是用來(lái)添加約束的耘戚,我們可以將約束添加到ConstraintLayout嗡髓,也可以將約束添加到另一個(gè)控件。比如說(shuō)收津,想讓Button位于布局的右下角饿这,就可以這樣添加約束,如下圖所示撞秋。
我們給Button的右邊和下邊添加了約束长捧,因此Button就會(huì)將自己定位到布局的右下角了。類(lèi)似地部服,如果我們想要讓Button居中顯示唆姐,那么就需要給它的上下左右都添加約束,如下圖所示廓八。
這就是添加約束最基本的用法了奉芦。
除此之外,我們還可以使用約束讓一個(gè)控件相對(duì)于另一個(gè)控件進(jìn)行定位剧蹂。比如說(shuō)声功,我們希望再添加一個(gè)Button,讓它位于第一個(gè)Button的正下方宠叼,并且間距64dp先巴,那么操作如下所示其爵。
現(xiàn)在添加約束的方式我們已經(jīng)學(xué)完了,那么該怎樣刪除約束呢伸蚯?其實(shí)也很簡(jiǎn)單摩渺,刪除約束的方式一共有三種,第一種用于刪除一個(gè)單獨(dú)的約束剂邮,將鼠標(biāo)懸浮在某個(gè)約束的圓圈上摇幻,然后該圓圈會(huì)變成紅色,這個(gè)時(shí)候單擊一下就能刪除了挥萌,如下圖所示绰姻。
第二種用于刪除某一個(gè)控件的所有約束,選中一個(gè)控件引瀑,然后它的左下角會(huì)出現(xiàn)一個(gè)刪除約束的圖標(biāo)狂芋,點(diǎn)擊該圖標(biāo)就能刪除當(dāng)前控件的所有約束了,如下所示憨栽。
第三種用于刪除當(dāng)前界面中的所有約束帜矾,點(diǎn)擊工具欄中的刪除約束圖標(biāo)即可,如下圖所示徒像。
Inspector
這樣我們就把ConstraintLayout的基本用法學(xué)完了黍特,接下來(lái)我們開(kāi)始學(xué)習(xí)一些進(jìn)階的內(nèi)容。
當(dāng)你選中任意一個(gè)控件的時(shí)候锯蛀,在右側(cè)的Properties區(qū)域就會(huì)出現(xiàn)很多的屬性選項(xiàng),如下圖所示次慢。
在這里我們就可以設(shè)置當(dāng)前控件的所有屬性旁涤,如文本內(nèi)容、顏色迫像、點(diǎn)擊事件等等劈愚。這些功能都非常簡(jiǎn)單,我就不再進(jìn)行詳細(xì)介紹闻妓,大家自己點(diǎn)一點(diǎn)就會(huì)操作了菌羽。
需要我們重點(diǎn)掌握的是Properties區(qū)域的上半部分,這部分也被稱(chēng)為Inspector由缆。
首先可以看到注祖,在Inspector中有一個(gè)縱向的軸和一個(gè)橫向的軸,這兩個(gè)軸也是用于確定控件的位置的均唉。我們剛才給Button的上下左右各添加了一個(gè)約束是晨,然后Button就能居中顯示了,其實(shí)就是因?yàn)檫@里縱橫軸的值都是50舔箭。如果調(diào)整了縱橫軸的比例罩缴,那么Button的位置也會(huì)隨之改變,如下圖所示。
不過(guò)箫章,雖然我們將橫軸的值拖動(dòng)到了100烙荷,但是Button并沒(méi)有緊貼到布局的最右側(cè),這是為什么呢檬寂?實(shí)際上奢讨,Android Studio給控件的每個(gè)方向上的約束都默認(rèn)添加了一個(gè)16dp的間距,從Inspector上面也可以明顯地看出來(lái)這些間距的值焰薄。如果這些默認(rèn)值并不是你想要的拿诸,可以直接在Inspector上進(jìn)行修改,如下圖所示:
可以看到塞茅,修改成0之后Button右側(cè)的間距就沒(méi)了亩码。
接下來(lái)我們?cè)賮?lái)學(xué)習(xí)一下位于Inspector最中間的那個(gè)正方形區(qū)域,它是用來(lái)控制控件大小的野瘦。一共有三種模式可選描沟,每種模式都使用了一種不同的符號(hào)表示,點(diǎn)擊符號(hào)即可進(jìn)行切換鞭光。
表示wrap content吏廉,這個(gè)我們很熟悉了,不需要進(jìn)行什么解釋惰许。
表示固定值席覆,也就是給控件指定了一個(gè)固定的長(zhǎng)度或者寬度值。
表示any size汹买,它有點(diǎn)類(lèi)似于match parent佩伤,但和match parent并不一樣,是屬于ConstraintLayout中特有的一種大小控制方式晦毙,下面我們來(lái)重點(diǎn)講解一下生巡。
首先需要說(shuō)明,在ConstraintLayout中是有match parent的见妒,只不過(guò)用的比較少孤荣,因?yàn)镃onstraintLayout的一大特點(diǎn)就是為了解決布局嵌套,既然沒(méi)有了布局嵌套须揣,那么match parent也就沒(méi)有多大意義了盐股。
而any size就是用于在ConstraintLayout中頂替match parent的,先看一下我們?cè)鯓邮褂胊ny size實(shí)現(xiàn)和match parent同樣的效果吧返敬。比如說(shuō)我想讓Button的寬度充滿(mǎn)整個(gè)布局遂庄,操作如下圖所示。
可以看到劲赠,我們將Button的寬度指定成any size涛目,它就會(huì)自動(dòng)充滿(mǎn)整個(gè)布局了秸谢。當(dāng)然還要記得將Button左側(cè)的間距設(shè)置成0才行。
那有的朋友可能會(huì)問(wèn)了霹肝,這和match parent有什么區(qū)別呢估蹄?其實(shí)最大的區(qū)別在于,match parent是用于填充滿(mǎn)當(dāng)前控件的父布局沫换,而any size是用于填充滿(mǎn)當(dāng)前控件的約束規(guī)則臭蚁。舉個(gè)例子更好理解,如果我們有一個(gè)新的Button讯赏,它的其中一個(gè)約束是添加到當(dāng)前這個(gè)Button上的垮兑,那么any size的效果也會(huì)發(fā)生改變,如下圖所示漱挎。
通過(guò)上圖的演示系枪,相信你已經(jīng)很好地理解any size的作用了。
Guidelines
現(xiàn)在你已經(jīng)對(duì)ConstraintLayout比較熟悉磕谅,并且能使用ConstraintLayout來(lái)編寫(xiě)一些簡(jiǎn)單的界面了私爷。不過(guò)目前有一個(gè)問(wèn)題可能還比較頭疼,剛才我們已經(jīng)實(shí)現(xiàn)了讓一個(gè)按鈕居中對(duì)齊的功能膊夹,如果我們想讓兩個(gè)按鈕共同居中對(duì)齊該怎么實(shí)現(xiàn)呢衬浑?
其實(shí)這個(gè)需求很常見(jiàn),比如說(shuō)在應(yīng)用的登錄界面放刨,都會(huì)有一個(gè)登錄按鈕和一個(gè)注冊(cè)按鈕工秩,不管它們是水平居中也好還是垂直居中也好,但肯定都是兩個(gè)按鈕共同居中的宏榕。
想要實(shí)現(xiàn)這個(gè)功能拓诸,僅僅用我們剛剛學(xué)的那些知識(shí)是不夠的,這需要用到ConstraintLayout中的一個(gè)新的功能麻昼,Guidelines。
下面我們還是通過(guò)實(shí)際操作來(lái)學(xué)習(xí)一下Guidelines的用法吧馋辈。比如現(xiàn)在已經(jīng)向界面中添加了登錄和注冊(cè)這兩個(gè)按鈕抚芦,如下圖所示。
然后我們希望讓這兩個(gè)按鈕在水平方向上居中顯示迈螟,在垂直方向上都距離底部64dp叉抡,那么就需要先添加一個(gè)垂直方向上的Guideline,如下圖所示答毫。
我來(lái)對(duì)上圖中的操作進(jìn)行一下解釋褥民。首先點(diǎn)擊通知欄中的Guidelines圖標(biāo)可以添加一個(gè)垂直或水平方向上的Guideline,這里我們需要的是垂直方向上的洗搂。而Guideline默認(rèn)是使用的dp尺消返,我們需要選中Guideline载弄,并點(diǎn)擊一下最上面的箭頭圖標(biāo)將它改成百比分尺,然后將垂直方向上的Guideline調(diào)整到50%的位置撵颊,這樣就將準(zhǔn)備工作做好了宇攻。
接下來(lái)我們開(kāi)始實(shí)現(xiàn)讓兩個(gè)按鈕在水平方向上居中顯示,并距離底部64dp的功能倡勇,如下圖所示逞刷。
可以看到,我們給登錄按鈕的右邊向Guideline添加約束妻熊,登錄按鈕的下面向底部添加約束夸浅,并拖動(dòng)按鈕讓它距離底部64dp。然后給注冊(cè)按鈕的左邊向Guideline添加約束扔役,注冊(cè)按鈕的下面向登錄按鈕的下面添加約束帆喇。這樣就實(shí)現(xiàn)了讓兩個(gè)按鈕在水平方向上居中顯示,在垂直方向上都距離底部64dp的功能了厅目。
自動(dòng)添加約束
不過(guò)如果界面中的內(nèi)容變得復(fù)雜起來(lái)番枚,給每個(gè)控件一個(gè)個(gè)地添加約束也是一件很繁瑣的事情。為此损敷,ConstraintLayout中支持自動(dòng)添加約束的功能葫笼,可以極大程度上簡(jiǎn)化那些繁瑣的操作。
自動(dòng)添加約束的方式主要有兩種拗馒,一種叫Autoconnect路星,一種叫Inference,我們先來(lái)看第一種诱桂。
想要使用Autoconnect洋丐,首先需要在工具欄中將這個(gè)功能啟用,默認(rèn)情況下Autoconnect是不啟用的挥等,如下圖所示友绝。
Autoconnect可以根據(jù)我們拖放控件的狀態(tài)自動(dòng)判斷應(yīng)該如何添加約束,比如我們將Button放到界面的正中央肝劲,那么它的上下左右都會(huì)自動(dòng)地添加上約束迁客,如下圖所示。
然后我們?cè)谶@個(gè)Button的下方再放置一個(gè)Button辞槐,效果如下掷漱。
可以看到,只需要將Button拖放到界面上榄檬,Autoconnect會(huì)判斷我們的意圖卜范,并自動(dòng)給控件添加約束。不過(guò)Autoconnect是無(wú)法保證百分百準(zhǔn)確判斷出我們的意圖的鹿榜,如果自動(dòng)添加的約束并不是你想要的話海雪,還可以在任何時(shí)候進(jìn)行手動(dòng)修改锦爵。總之喳魏,可以把它當(dāng)成一個(gè)輔助工具棉浸,但不能完全靠它去添加控件的約束。
以上是Autoconnect的用法刺彩,接下來(lái)我們看一下Inference的用法迷郑。Inference也是用于自動(dòng)添加約束的,但它比Autoconnect的功能要更為強(qiáng)大创倔,因?yàn)锳utoConnect只能給當(dāng)前操作的控件自動(dòng)添加約束嗡害,而Inference會(huì)給當(dāng)前界面中的所有元素自動(dòng)添加約束。因而Inference比較適合用來(lái)實(shí)現(xiàn)復(fù)雜度比較高的界面畦攘,它可以一鍵自動(dòng)生成所有的約束霸妹。
下面我們就通過(guò)一個(gè)例子來(lái)演示一下Inference的用法,比如界面上現(xiàn)在有兩個(gè)TextView知押,兩個(gè)EditText叹螟,和兩個(gè)Button,如下圖所示台盯。
接下來(lái)我們先將各個(gè)控件按照界面設(shè)計(jì)的位置進(jìn)行擺放罢绽,擺放完成之后點(diǎn)擊一下工具欄上的Infer Constraints按鈕,就能為所有控件自動(dòng)添加約束了静盅,如下圖所示良价。
現(xiàn)在運(yùn)行一下程序,最終效果如下圖所示:
到這里蒿叠,我們基本就把ConstraintLayout中的重要用法都概括到了明垢,通過(guò)本篇的學(xué)習(xí),大家也對(duì)ConstraintLayout有了比較深入的認(rèn)識(shí)市咽。當(dāng)然痊银,ConstraintLayout目前還是處于beta版本,有很多的功能仍然在改進(jìn)當(dāng)中施绎。比如說(shuō)曼验,beta3版本中引入的Chains功能就是一個(gè)很強(qiáng)大的新功能,不過(guò)由于這個(gè)功能需要配合Android Studio 2.3來(lái)使用粘姜,而2.3目前也還沒(méi)有出正式版,因此我就沒(méi)在本篇文章中加入這部分內(nèi)容的介紹熔酷。等以后ConstraintLayout的功能更加豐富的時(shí)候孤紧,我可能會(huì)再寫(xiě)一篇ConstraintLayout的高級(jí)用法,來(lái)補(bǔ)足這方面的內(nèi)容吧拒秘。
完号显。臭猜。。押蚤。蔑歌。。揽碘。次屠。。雳刺。劫灶。。掖桦。本昏。。枪汪。涌穆。。雀久。宿稀。。
文章原創(chuàng)作者GuoLin 書(shū)籍推薦
郭林大神原創(chuàng)android 書(shū)籍:《第一行代碼 android》