前言
ConstraintLayout是安卓后期推出的一個優(yōu)秀的布局組件蟆盹,它最主要的一個優(yōu)點(diǎn),就是可以有效地解決布局嵌套過多的問題。我們平時編寫界面怜珍,復(fù)雜的布局總會伴隨著多層的嵌套渡紫,而嵌套越多到推,程序的性能也就越差。ConstraintLayout則是使用約束的方式來指定各個控件的位置和關(guān)系的惕澎,它有點(diǎn)類似于RelativeLayout莉测,但遠(yuǎn)比RelativeLayout要更強(qiáng)大。
AndroidStudio提供的插件可以支持ConstraintLayout拖拽的方式布局唧喉,也可以用手寫代碼布局捣卤,我們用兩篇文章分別來記錄下使用方法。
開始
下面我們開始用邊學(xué)邊練的方式來進(jìn)行學(xué)習(xí)八孝,首先打開你的Android Studio董朝,并新建一個ConstraintLayoutTest項(xiàng)目。
為了要使用ConstraintLayout干跛,我們需要在app/build.gradle文件中添加ConstraintLayout的依賴子姜,如下所示。
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
}
現(xiàn)在打開res/layout/activity_main.xml文件楼入,由于這是一個新建的空項(xiàng)目哥捕,Android Studio會自動幫我們創(chuàng)建好一個布局,如下圖所示嘉熊。
我們可以看到遥赚,現(xiàn)在主操作區(qū)域內(nèi)有兩個類似于手機(jī)屏幕的界面,左邊的是預(yù)覽界面阐肤,右邊的是藍(lán)圖界面凫佛。這兩部分都可以用于進(jìn)行布局編輯工作,區(qū)別是左邊部分主要用于預(yù)覽最終的界面效果孕惜,右邊部分主要用于觀察界面內(nèi)各個控件的約束情況愧薛。
基本操作
下面我們來學(xué)習(xí)一些具體的操作吧,ConstraintLayout的基本用法很簡單诊赊,比如我們想要向布局中添加一個按鈕厚满,那么只需要從左側(cè)的Palette區(qū)域拖一個Button進(jìn)去就可以了,如下圖所示碧磅。
雖說現(xiàn)在Button已經(jīng)添加到界面上了碘箍,但是由于我們還沒有給Button添加任何的約束遵馆,因此Button并不知道自己應(yīng)該出現(xiàn)在什么位置。現(xiàn)在我們在預(yù)覽界面上看到的Button位置并不是它最終運(yùn)行后的實(shí)際位置丰榴,如果一個控件沒有添加任何約束的話货邓,它在運(yùn)行之后會自動位于界面的左上角。
那么下面我們就來給Button添加約束四濒,每個控件的約束都分為垂直和水平兩類换况,一共可以在四個方向上給控件添加約束,如下圖所示盗蟆。
上圖中Button的上下左右各有一個圓圈戈二,這圓圈就是用來添加約束的,我們可以將約束添加到ConstraintLayout喳资,也可以將約束添加到另一個控件觉吭。比如說,想讓Button位于布局的右下角仆邓,就可以這樣添加約束鲜滩,如下圖所示。
我們給Button的右邊和下邊添加了約束节值,因此Button就會將自己定位到布局的右下角了徙硅。類似地,如果我們想要讓Button居中顯示搞疗,那么就需要給它的上下左右都添加約束嗓蘑,如下圖所示。
這就是添加約束最基本的用法了贴汪。
除此之外脐往,我們還可以使用約束讓一個控件相對于另一個控件進(jìn)行定位。比如說扳埂,我們希望再添加一個Button,讓它位于第一個Button的正下方瘤礁,并且間距64dp阳懂,那么操作如下所示。
現(xiàn)在添加約束的方式我們已經(jīng)學(xué)完了柜思,那么該怎樣刪除約束呢岩调?其實(shí)也很簡單,刪除約束的方式一共有三種赡盘,第一種用于刪除一個單獨(dú)的約束号枕,將鼠標(biāo)懸浮在某個約束的圓圈上,然后該圓圈會變成紅色陨享,這個時候單擊一下就能刪除了葱淳,如下圖所示钝腺。
第二種用于刪除某一個控件的所有約束,選中一個控件赞厕,然后它的左下角會出現(xiàn)一個刪除約束的圖標(biāo)艳狐,點(diǎn)擊該圖標(biāo)就能刪除當(dāng)前控件的所有約束了,如下所示皿桑。
第三種用于刪除當(dāng)前界面中的所有約束毫目,點(diǎn)擊工具欄中的刪除約束圖標(biāo)即可,如下圖所示诲侮。
Inspector
這樣我們就把ConstraintLayout的基本用法學(xué)完了镀虐,接下來我們開始學(xué)習(xí)一些進(jìn)階的內(nèi)容。
當(dāng)你選中任意一個控件的時候沟绪,在右側(cè)的Properties區(qū)域就會出現(xiàn)很多的屬性選項(xiàng)粉私,如下圖所示。
在這里我們就可以設(shè)置當(dāng)前控件的所有屬性近零,如文本內(nèi)容诺核、顏色、點(diǎn)擊事件等等久信。這些功能都非常簡單窖杀,我就不再進(jìn)行詳細(xì)介紹,大家自己點(diǎn)一點(diǎn)就會操作了裙士。
需要我們重點(diǎn)掌握的是Properties區(qū)域的上半部分入客,這部分也被稱為Inspector。
首先可以看到腿椎,在Inspector中有一個縱向的軸和一個橫向的軸桌硫,這兩個軸也是用于確定控件的位置的。我們剛才給Button的上下左右各添加了一個約束啃炸,然后Button就能居中顯示了铆隘,其實(shí)就是因?yàn)檫@里縱橫軸的值都是50。如果調(diào)整了縱橫軸的比例南用,那么Button的位置也會隨之改變膀钠,如下圖所示。
不過裹虫,雖然我們將橫軸的值拖動到了100肿嘲,但是Button并沒有緊貼到布局的最右側(cè),這是為什么呢筑公?實(shí)際上雳窟,Android Studio給控件的每個方向上的約束都默認(rèn)添加了一個16dp的間距,從Inspector上面也可以明顯地看出來這些間距的值匣屡。如果這些默認(rèn)值并不是你想要的封救,可以直接在Inspector上進(jìn)行修改拇涤,如下圖所示:
可以看到,修改成0之后Button右側(cè)的間距就沒了兴泥。
接下來我們再來學(xué)習(xí)一下位于Inspector最中間的那個正方形區(qū)域工育,它是用來控制控件大小的。一共有三種模式可選搓彻,每種模式都使用了一種不同的符號表示如绸,點(diǎn)擊符號即可進(jìn)行切換。
表示wrap content旭贬,這個我們很熟悉了怔接,不需要進(jìn)行什么解釋。
表示固定值稀轨,也就是給控件指定了一個固定的長度或者寬度值扼脐。
表示any size,它有點(diǎn)類似于match parent奋刽,但和match parent并不一樣瓦侮,是屬于ConstraintLayout中特有的一種大小控制方式,下面我們來重點(diǎn)講解一下佣谐。
首先需要說明肚吏,在ConstraintLayout中是有match parent的,只不過用的比較少狭魂,因?yàn)镃onstraintLayout的一大特點(diǎn)就是為了解決布局嵌套罚攀,既然沒有了布局嵌套,那么match parent也就沒有多大意義了雌澄。
而any size就是用于在ConstraintLayout中頂替match parent的斋泄,先看一下我們怎樣使用any size實(shí)現(xiàn)和match parent同樣的效果吧。比如說我想讓Button的寬度充滿整個布局镐牺,操作如下圖所示炫掐。
可以看到,我們將Button的寬度指定成any size任柜,它就會自動充滿整個布局了卒废。當(dāng)然還要記得將Button左側(cè)的間距設(shè)置成0才行。
那有的朋友可能會問了宙地,這和match parent有什么區(qū)別呢?其實(shí)最大的區(qū)別在于逆皮,match parent是用于填充滿當(dāng)前控件的父布局宅粥,而any size是用于填充滿當(dāng)前控件的約束規(guī)則。舉個例子更好理解电谣,如果我們有一個新的Button秽梅,它的其中一個約束是添加到當(dāng)前這個Button上的抹蚀,那么any size的效果也會發(fā)生改變,如下圖所示企垦。
通過上圖的演示环壤,相信你已經(jīng)很好地理解any size的作用了。
Guidelines
現(xiàn)在你已經(jīng)對ConstraintLayout比較熟悉钞诡,并且能使用ConstraintLayout來編寫一些簡單的界面了郑现。不過目前有一個問題可能還比較頭疼,剛才我們已經(jīng)實(shí)現(xiàn)了讓一個按鈕居中對齊的功能荧降,如果我們想讓兩個按鈕共同居中對齊該怎么實(shí)現(xiàn)呢接箫?
其實(shí)這個需求很常見,比如說在應(yīng)用的登錄界面朵诫,都會有一個登錄按鈕和一個注冊按鈕辛友,不管它們是水平居中也好還是垂直居中也好,但肯定都是兩個按鈕共同居中的剪返。
想要實(shí)現(xiàn)這個功能废累,僅僅用我們剛剛學(xué)的那些知識是不夠的,這需要用到ConstraintLayout中的一個新的功能脱盲,Guidelines邑滨。
下面我們還是通過實(shí)際操作來學(xué)習(xí)一下Guidelines的用法吧。比如現(xiàn)在已經(jīng)向界面中添加了登錄和注冊這兩個按鈕宾毒,如下圖所示驼修。
然后我們希望讓這兩個按鈕在水平方向上居中顯示,在垂直方向上都距離底部64dp诈铛,那么就需要先添加一個垂直方向上的Guideline乙各,如下圖所示。
我來對上圖中的操作進(jìn)行一下解釋幢竹。首先點(diǎn)擊通知欄中的Guidelines圖標(biāo)可以添加一個垂直或水平方向上的Guideline耳峦,這里我們需要的是垂直方向上的。而Guideline默認(rèn)是使用的dp尺焕毫,我們需要選中Guideline蹲坷,并點(diǎn)擊一下最上面的箭頭圖標(biāo)將它改成百分比尺,然后將垂直方向上的Guideline調(diào)整到50%的位置邑飒,這樣就將準(zhǔn)備工作做好了循签。
接下來我們開始實(shí)現(xiàn)讓兩個按鈕在水平方向上居中顯示,并距離底部64dp的功能疙咸,如下圖所示县匠。
可以看到,我們給登錄按鈕的右邊向Guideline添加約束,登錄按鈕的下面向底部添加約束乞旦,并拖動按鈕讓它距離底部64dp贼穆。然后給注冊按鈕的左邊向Guideline添加約束,注冊按鈕的下面向登錄按鈕的下面添加約束兰粉。這樣就實(shí)現(xiàn)了讓兩個按鈕在水平方向上居中顯示故痊,在垂直方向上都距離底部64dp的功能了。
自動添加約束
不過如果界面中的內(nèi)容變得復(fù)雜起來玖姑,給每個控件一個個地添加約束也是一件很繁瑣的事情愕秫。為此,ConstraintLayout中支持自動添加約束的功能客峭,可以極大程度上簡化那些繁瑣的操作豫领。
自動添加約束的方式主要有兩種,一種叫Autoconnect舔琅,一種叫Inference等恐,我們先來看第一種。
想要使用Autoconnect备蚓,首先需要在工具欄中將這個功能啟用课蔬,默認(rèn)情況下Autoconnect是不啟用的,如下圖所示郊尝。
Autoconnect可以根據(jù)我們拖放控件的狀態(tài)自動判斷應(yīng)該如何添加約束二跋,比如我們將Button放到界面的正中央,那么它的上下左右都會自動地添加上約束流昏,如下圖所示扎即。
然后我們在這個Button的下方再放置一個Button,效果如下况凉。
可以看到谚鄙,只需要將Button拖放到界面上,Autoconnect會判斷我們的意圖刁绒,并自動給控件添加約束闷营。不過Autoconnect是無法保證百分百準(zhǔn)確判斷出我們的意圖的,如果自動添加的約束并不是你想要的話知市,還可以在任何時候進(jìn)行手動修改傻盟。總之嫂丙,可以把它當(dāng)成一個輔助工具娘赴,但不能完全靠它去添加控件的約束。
以上是Autoconnect的用法跟啤,接下來我們看一下Inference的用法筝闹。Inference也是用于自動添加約束的媳叨,但它比Autoconnect的功能要更為強(qiáng)大腥光,因?yàn)锳utoConnect只能給當(dāng)前操作的控件自動添加約束关顷,而Inference會給當(dāng)前界面中的所有元素自動添加約束。因而Inference比較適合用來實(shí)現(xiàn)復(fù)雜度比較高的界面武福,它可以一鍵自動生成所有的約束议双。
下面我們就通過一個例子來演示一下Inference的用法,比如界面上現(xiàn)在有兩個TextView捉片,兩個EditText平痰,和兩個Button粤策,如下圖所示矮冬。
接下來我們先將各個控件按照界面設(shè)計的位置進(jìn)行擺放,擺放完成之后點(diǎn)擊一下工具欄上的Infer Constraints按鈕别伏,就能為所有控件自動添加約束了莹规,如下圖所示赔蒲。
現(xiàn)在運(yùn)行一下程序,最終效果如下圖所示: