- 和 LinearLayout、RelativeLayout等一樣,都是繼承自ViewGroup,是view容器
- 能夠用較少的視圖層級創(chuàng)建出復(fù)雜的視圖。
- 與RelativeLayout 類似,view 的擺放位置取決于 view 之間 或者 view 與 parent 之間的相對位置
- 可以完全的通過拖拽實現(xiàn)某個頁面 (很方便,但是也需要了解如何手動編寫xml)
- ConstraintLayout 最低兼容到 API 9 (即Android 2.3)
方法 (1):
最簡單,最直接的方式是,切換到 xml 的 design 視圖模式下,然后在左上角的 Layouts 中直接 雙擊 ConstraintLayout , 然后就會彈窗提示是否添加到依賴,點擊 ok,然后坐等依賴成功即可。
最簡單最直接的添加依賴方式
方法 (2):
在當(dāng)前Modle 的 build.gradle 中添加如下內(nèi)容:
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.2'
}
直接看圖就好了
image.png
這個就不說了,直接新建一個xml 文件,將其根節(jié)點手動指定 為 ConstraintLayout即可。
約束就是用來控制view的相對位置的參數(shù)信息,其含義類似于RelativeLayout中的 layout_below 、layout_up等
拖拽view到編輯區(qū)并添加約束
在上圖中,我們將某個view從 Palette 面板中拖到編輯區(qū)域之后,會在該 view 周邊生成一個邊線,四個角上是白色填充的小方塊,四條邊線中間是空心圓圈,底部還有兩個按鈕。各自的作用分別如下:
點擊該view,讓view周邊顯示出小方塊和小圓圈,點擊小圓圈按住不松手(此時該小圓圈被稱為??),然后拖拽到另一個錨點位置后松手, 該錨點可以是另一個view的小圓圈,也可以是parent 的布局邊界,也可以是 guideLine ( guideLine 后面會有介紹 )。松手之后,就創(chuàng)建好了一個約束條件,該約束條件會有一個默認(rèn)的8dp 的margin 值。
(1):
將 view 添加到 ConstraintLayout 之后,至少需要給該view分別在 X 軸和Y軸上各定義一個約束條件。
這些約束條件可以是相對于其他view的,也可以是相對于parent的,甚至是相對于其他 invisiable 的view。這些約束條件用來確定該view在X軸和Y軸的位置,所以至少需要分別在 X 軸 和 Y 軸定義一個約束條件,當(dāng)然,實際使用的時候,可能會定義許多個約束條件。
(2):
我們將view拖到 LayoutEditor(布局編輯器)之后,如果未指定約束條件,那么在編輯器預(yù)覽界面中該view會處于我們放置的位置,但是,實際部署運行之后會居于界面左上角,也就是從 [0,0] 坐標(biāo)點開始繪制。
(3):
相連接的錨點和把手必須在一個平面中,垂直平面的錨點只能和垂直平面的把手互連
也就是說,A 的 左邊界或者右邊界中的錨點只能連接到 B 的左邊界或者右邊界的錨點,不能連接到B的上邊界或下邊界錨點;BaseLine 的錨點也只能連接到另一個View的BaseLine 錨點。
(4):
每個把手只能用來創(chuàng)建一個約束條件,但是一個錨點卻可以連接到不同view的把手上。
singleRefresh.gif
通過上圖我們可以總結(jié)出移除約束的三種方式:
(1)、相對于父布局的約束(Parent position)
把手與父布局的邊界相連接,父布局的邊界作為錨點
Parent position
(2)、序列式約束(Order Position)
view 與 view 之間的位置約束,把手與其他view相連接,其他view的把手作為錨點。
Order Position
(3)、對齊式約束(Alignment)
A 的邊線或中間線與 B的邊線或中間線對齊(遵守上面注意事項中的3)
如下圖,分為兩種,一種是不帶margin的對齊,對應(yīng)下圖中的左半部分;一種是待margin的對齊,對應(yīng)下圖中的有半部分
Alignment
如果按照邊線區(qū)分的話,可以分為上邊線對齊,下邊線對齊,左邊線對齊,右邊線對齊,中間線對齊
(4)、基線對齊式約束(BaseLine Alignment)
基線與基線連接形成的約束。
BaseLine Alignment
(5)、輔助線約束(Constrain to a guideline)
基于輔助線的約束條件,把手連接到輔助線
Constrain to a guideline
1):輔助線及輔助線約束的創(chuàng)建
guideLine的創(chuàng)建方式及部分按鈕的作用
GuideLine 是編輯布局時的一條輔助線,可以是水平的,也可以是垂直的。該輔助線只在代碼中對程序猿可見,app部署之后在頁面中是看不到該線的。
如上圖,我們點擊工具欄中的圖標(biāo)之后,就可以選擇創(chuàng)建一個水平或者垂直的 guideLine。
guideLine的添加和使用.gif
上圖中,我們創(chuàng)建了一個垂直的guideLine ,然后以它為錨點為兩個view添加了約束。
2):輔助線的擺放模式及擺放模式的更改
在上一個圖中,我們會看到創(chuàng)建完 guideLine后, 頂部出現(xiàn)一個小圓圈包含一個向左的小箭頭,表示guideLine 的位置是相對于父布局的左邊界多少 dp;點擊該小圓點,箭頭變成向右的,表示此時guideLine 的位置是相對于父布局右邊界多少dp;再次點擊小圓圈,箭頭換成了 % ,表示 guideLine 的 X 軸坐標(biāo)占父布局的百分比。這三種情況分別對應(yīng) guideLine 的三個屬性值,具體如下:
layout_constraintGuide_begin ?? 指定 guideLine 到父布局的左邊界或上邊界的具體距離
layout_constraintGuide_end ?? 指定 guideLine 到父布局的右邊界或下邊界的具體距離
layout_constraintGuide_percent ?? 指定 guideLine 占寬度或高度的百分比距離
注意
創(chuàng)建了 guideLine 之后,拖拽的時候,如果左側(cè)或者頂部并沒有那個小圓圈,那么我們該怎么去切換 guideLine 的擺放模式呢?
其實很簡單,我們上面已經(jīng)知道了三種擺放模式 對應(yīng) guideLine 的三個屬性,所以,我們直接從 xml 代碼中手動修改模式,然后再回到 design 模式中拖拽到期望的位置即可。
代碼如下:
??
(6)、鏈條式約束(chain)
請看下面的第七大知識點。
所謂的偏移率可以理解成距離父布局左邊框的距離占父布局寬度的百分比,約束的偏移率可以用來調(diào)整view的位置。
如果我們給某個view的左邊框和右邊框同時添加了約束,那么在properties面板中就會出現(xiàn) 調(diào)整水平bias的拖動條(垂直方向上同理) ,bias 調(diào)整條的使用有如下兩種情況:
下面所說的view的大小指的是view的 width 或者 height 的取值。
在 ConstraintLayout 中,view 的width 、height 的取值有三種,分別是:
- 具體數(shù)值,如 99dp
- wrap_content , 包裹內(nèi)容
- match_constraint,填滿約束區(qū)域,0dp等價于match_constraint
這里需要注意:官方文檔中指出被ConstraintLayout 包裹的控件不支持 match_parent 的取值,但實際在AS中使用的時候,并沒有match_constraint ,所以實際使用時 使用0dp 表示 match_constraint 即可
調(diào)整約束偏移率1
如上圖,當(dāng)我們給某個 view 的 左邊和右邊(或者上邊和下邊)都添加了約束,并且該View 的大小是具體的值或者 wrapContent的時候,那么該 view 默認(rèn)會居中,也就是說 偏移率 bias 是 50%。而且在最右側(cè)的 properties 面板中會顯示出 偏移率調(diào)整條。我們通過這個調(diào)整條就可以調(diào)整 view 的偏移率,當(dāng)然,直接拖動view也可以調(diào)整偏移率。
調(diào)整約束偏移率2--注意:bias 的計算是將margin排除之后計算的結(jié)果
在上面這個圖中,我們發(fā)現(xiàn),給View 左右兩側(cè)都添加約束之后,雖然右側(cè) properties 面板中偏移率調(diào)整條中顯示是 50% ,但是view 并沒有居中。
這是因為,我們在將view添加到編輯區(qū)并添加了左側(cè)和上側(cè)的約束之后,又手動調(diào)整了view的位置,讓view距離左側(cè)和上側(cè)有一定的距離,這個距離是margin 。而在計算 bias 的時候,被除數(shù)(也就是view可用的擺放區(qū)域)并不包含margin 值,所以,我們看到雖然bias 是 50 % ,但 view 沒有居于父布局的center位置。
bias_0dp.gif
上圖中,我們給button的上邊框和下邊框都添加了約束,此時,出現(xiàn)了 垂直方向的bias 調(diào)整條,然后我們將height 手動設(shè)置為0dp,然后我們拖動bias 調(diào)整條,我們會發(fā)現(xiàn),此時調(diào)整條無效。這是因為:我們將height 設(shè)置為 0dp 之后,view就會填滿約束區(qū),也就是說,該view 的父布局在垂直方向上已經(jīng)沒有額外的空間供 該view在垂直方向上移動
填滿約束區(qū)的意思其實就是,填滿除margin 之外的區(qū)域
?調(diào)整view 大小 + 展開和收起properties面板
我們可以在布局編輯界面中拖動 view四個角上的白色小方塊來調(diào)整其大小,這種方式屬于硬編碼模式,不會導(dǎo)致其他view或者屏幕的重新測量。如果我們想使用更多的方式去調(diào)整 view 的大小,那么就需要使用 properties 面板了。
0dp
使用約束調(diào)整view的大小時,只能實現(xiàn)填滿約束的情況。如上圖,如果我們想讓button的寬度填滿約束區(qū),那么我們就先給該button的左邊和右邊都加上約束,然后設(shè)置其大小為 0dp 即可。(高度填滿約束區(qū)同理)
注意:
- 在上面的動圖中,我們看到在button的四周其實還會有一個白色邊距,這個邊距是創(chuàng)建約束時默認(rèn)的margin 值-- 8dp ,我們前面已經(jīng)說過,約束區(qū)不包括margin值。(關(guān)于如何修改這個margin值,后面會有介紹)
- 在上面的動圖中,拖拽第二個button的時候,設(shè)置完約束之后,我們選擇了 match_parent ,看上去效果和 0dp 沒啥區(qū)別,但是官方文檔不止一次的強調(diào)不能使用 match_parent , 而且也有部分網(wǎng)友反饋使用match_parent 時出錯,所以,保守起見,在設(shè)置被 constraintLayout 包裹的view的大小時,我們還是用 0dp吧。(具體為啥暫時不清楚,后面有時間了再去源碼中翻看一下)
properties面板中包含調(diào)整尺寸和約束的工具,以及部分常用屬性。
我們先來看一張圖:
properties 面板中尺寸調(diào)整工具圖標(biāo)
上圖中,各個標(biāo)識對應(yīng)的功能分別如下:
圖中所示 3 寬高模式共有三種,對應(yīng)的圖標(biāo)與模式分別如下:
點擊上面的幾個圖標(biāo),就可以在三種模式之間任意切換 , 從而實現(xiàn)view尺寸的調(diào)整。
注意: 在設(shè)置被 ConstraintLayout 包裹的view 的 width 或者 height 的時候千萬不要使用 match_parent , 而必須使用 match constraints (也就是 0dp).
某些時候,我們需要控制某個view的寬是高的 百分之多少,或者 高是寬的百分值多少,之前我們可能會使用 LinearLayout 或者 FrameLayout , 然后使用weight 屬性去控制,或者直接使用 固定的dp 值,在或者直接在代碼中手動的獲取并計算寬高,實際上用這三種方式實現(xiàn)的時候一方面可能會增加布局嵌套,另一方面可能會手寫較多的代碼,而且,對設(shè)計稿的還原度也沒那么高。but , 如果使用constraintLayout ,我們只需要輕輕的拖拽幾下,然后輸入比率值,然后回車,搞定。。。具體請看下面的例子
注意:如果我們想使用 ratio 的形式去設(shè)置寬高, 那么必須保證 寬高 中 至少有一項使用了 0dp(即 match_constraint)?
(1)、寬度是0dp(寬度是 match_constraint)
寬度是0dp
在上圖中,我們拖動一個 button 到編輯區(qū),先添加約束,此時默認(rèn)的寬高都是 wrap_content , 我們會看到 properties 面板中的方形區(qū)域 左上角 并沒有三角符號,然后我們點擊 方形區(qū)域 中的 寬高模式圖標(biāo),手動將寬度切換為 0dp(即 match_constraint) 。 此時,我們會發(fā)現(xiàn),方形區(qū)域右上角出現(xiàn)一個 空心的三角區(qū)域,然后我們點擊一下,就變成了實心的三角,并且方形區(qū)域右下方會出現(xiàn) ratio 字樣 和 一個 輸入框,我們直接在輸入框中 輸入 ?? 的比率并回車,這樣就實現(xiàn)了 寬 和 高 的比率設(shè)置。
此外,在上圖中我們發(fā)現(xiàn),當(dāng)點擊空心三角,啟用 比率設(shè)置之后,不但空心三角變成了實線三角,而且properties面板中方形區(qū)域的左邊框和有邊框的兩個小圓圈(把手)直接使用 直線連通了,這個連通的直線表示:當(dāng)前寬度是0dp,寬度的具體尺寸以高度為基準(zhǔn)
(2)、高度是0dp
高度是0dp.gif
在上圖中,我們拖動一個 button 到編輯區(qū),添加完約束,手動將寬度切換為 0dp(即 match_constraint) 。 點擊 空心的三角區(qū)域,啟用ratio 設(shè)置,并設(shè)置了寬高比率。
在上圖中,我們發(fā)現(xiàn),而且properties面板中方形區(qū)域的垂直方向的兩個小圓圈(把手)被直線連通了,表示:當(dāng)前高度是0dp,高度的具體尺寸以寬度為基準(zhǔn)。
注意:
- ratio 下方的輸入框中,格式是固定的即—— 寬度:高度
(3)、寬高都是0dp(必看此處!??!)
singleRefresh.gif
如上圖,當(dāng)寬高都是0dp 的時候,我們點擊空心三角啟用ratio模式后,先采用的是 高度為0dp的模式(即,高度的具體值以寬度為基準(zhǔn));接著,我們再點擊實心三角,此時會切換到 寬度為 0dp 的模式(即,寬度的具體值以高度為基準(zhǔn));然后,我們再點實心三角,此時已經(jīng)退出了比率模式,但是ratio和輸入框還在,但是輸入內(nèi)容也不會起作用;然后,我們再點實心三角,完全退出比率模式,三角標(biāo)消失。
margin設(shè)置工具
如果我們需要給多個view、或者單個view的多個側(cè)邊設(shè)置一樣的margin值,那么我們就可以使用編輯界面工具欄中的 margin 設(shè)置工具--也就是上圖中被紅色框圈出來的數(shù)字 8 ,這里的 8 表示:
我們給某個view添加約束之后,默認(rèn)就會添加一個 8dp 的margin值。
那么,具體如何添加margin并修改默認(rèn)margin值呢?請看下面的動圖。
使用工具欄中的工具批量設(shè)置margin
在上面的動圖中,我們可以看到,我們添加約束之后,就會直接帶有一個8dp的margin值,并且對應(yīng)的在properties 面板中也會有margin值的展示。
修改默認(rèn)margin值
如上圖,如果我們需要修改這個默認(rèn)的margin值,那么就 單擊工具欄中的 “8” ,此時會彈出面板,在彈出的面板中有系統(tǒng)預(yù)設(shè) 的 0、8、16、24 可供選擇,也可以直接輸入你需要的margin 值。需要注意,單位是dp。而且,修改之后的margin值只對之后添加的view生效,對修改之前已經(jīng)添加的view不生效。
補充:為什么預(yù)設(shè)的margin值都是8的倍數(shù)? 預(yù)設(shè)8dp是基于Material Design 設(shè)計理念而設(shè)置的,
在上一節(jié)中我們知道了如何去批量的設(shè)置margin值,那么,如果我們需要調(diào)整某個側(cè)邊的margin值該怎么做呢?看下圖:
margin.gif
如上圖,當(dāng)我們將光標(biāo)挪到 properties 面板中方形區(qū)域的表示margin的數(shù)字上時,數(shù)字就變成了一個輸入框和一個下拉按鈕,點擊下拉按鈕會有預(yù)設(shè)的margin值,都是8 的倍數(shù);也可以直接從輸入框中輸入我們想要的margin值,然后回車,就是這么簡單。
所謂鏈條,就是一組相互連接的view,這些view之間具有雙向的位置約束,如下圖:
水平方向的鏈條
在上圖中,A的右邊框位置取決于B的左邊框位置(A 右邊框的把手連接到B左邊框的錨點),B的左邊框位置也取決于A的右邊框(B 左邊框的把手連接到A右邊框的錨點),這樣,A和B就組合成了一個水平的鏈條。
鏈條可分為垂直鏈條和水平鏈條。
快速創(chuàng)建鏈條的方法是,選中需要添加到鏈條中的view,然后右擊,選擇Center Horizontally 或 Center Vertically,這樣就完成了一個水平或垂直鏈條的創(chuàng)建。具體如下圖:
水平鏈條的創(chuàng)建
注意事項:
- 只有水平排列的view才能通過 center horizontally 創(chuàng)建水平鏈條(垂直鏈條同理)
- 在創(chuàng)建水平鏈條式,多個view之間的位置可以有高低偏差,但是偏差不能過大,通常是 后一個view的頂部邊框不能低于前一個view的底部邊框,如果超出這個范圍將無法創(chuàng)建鏈條(垂直鏈條同理)
水平鏈條中view的排列方式有如下幾種:(垂直鏈條中模式一致,只不過view的排列變成了垂直的)
以下模式依次對應(yīng)上圖中的 1、2、3、4
在水平鏈條中,鏈條頭就是最左側(cè)的view;垂直鏈條中,鏈條頭是最頂端的view。
鏈條模式的切換
如上圖,創(chuàng)建鏈條之后,默認(rèn)spread 模式。如果想切換模式,則選中鏈條中的任一view, 然后點擊view下方的 鏈條圖標(biāo),即可實現(xiàn) spread, spread inside, 和 packed 模式之間的切換。鏈條圖標(biāo)如下:
鏈條圖標(biāo)
- 一個view在同一時刻既可以是水平鏈條中的一部分,也可以是垂直鏈條中的一部分,這個屬性能讓我們更靈活的創(chuàng)建出一個Grid柵格界面
- 多個view的位置大致在同一個水平軸或者垂直軸的時候,才可以創(chuàng)建出水平或者垂直鏈條(這一點在如何創(chuàng)建鏈條中有說明)
- 雖然有水平鏈條也有垂直鏈條,但是鏈條本身并不會對齊它所包含的view,所以必要的時候需要借助 對齊約束(alignment)或者 輔助線約束(guideLine)等實現(xiàn)view對齊
推斷式約束--Infer constraints
如上圖,除了手動的為每一個view添加約束之外,我們也可以先將view移動到我們期望的位置,然后點擊工具欄中的 Infer Constraints 圖標(biāo)讓AndroidStudio自動幫我們添加約束條件。圖標(biāo)如下:
Infer Constraints 圖標(biāo)
推斷式約束的大致原理是:檢測所有view的擺放位置,然后根據(jù)當(dāng)前的位置為這些view確定出最高效的約束條件。 但是在實際使用的時候,可能還需要我們自己手動的根據(jù)不同的屏幕朝向或者屏幕尺寸做出適當(dāng)?shù)恼{(diào)整。
Autoconnect 在默認(rèn)情況下是處于關(guān)閉狀態(tài)的,我們可以通過點擊工具欄中的 Turn on Autoconnect 圖標(biāo)手動的開啟或關(guān)閉。圖標(biāo)如下:
Autoconnect圖標(biāo)
創(chuàng)建Autoconnect 自動連接式約束
在上圖中,Autoconnect 可以手動的開啟或者關(guān)閉,開啟之后會自動為之后添加到 constraintLayout 中的view添加兩個或多個約束條件,而對開啟之前添加的view不生效。
此處根據(jù)上圖我們也發(fā)現(xiàn):
- 開啟 AutoConnect 之后, 只有將view拖到某些位置才會自動創(chuàng)建約束,也就是說,并不一定能為每一個添加進(jìn)來的view創(chuàng)建約束。
在上圖中,第三個被添加的button雖然是在開啟 AutoConnect之后添加的,但是并沒有創(chuàng)建任何約束- 使用AutoConnect為View創(chuàng)建約束的時候,并不能保證同時在水平和垂直方向上都創(chuàng)建約束
在上圖中,我們第二個被添加的button,是在開啟 AutoConnect之后添加的,雖然自動給添加約束,但是我們也看到了,只添加了水平方向的約束,而沒有添加垂直方向的約束,此時垂直方向的約束就需要我們手動的去添加。
經(jīng)過前面的介紹,兩者的對比其實很明顯了:
- Infer Constraints 會為所有Constraint 中所包裹的還沒有約束的view創(chuàng)建約束;而AutoConnect 只會為開啟該功能之后的、在特定位置的view創(chuàng)建約束
- Infer Constraints 能同時創(chuàng)建垂直和水平的約束;而AutoConnect 可能只會創(chuàng)建單一坐標(biāo)軸方向上的約束。
所以,我覺的還是用 InferConstraints 更為方便一些。
工具欄中的圖標(biāo)及其含義
在文中之前部分的介紹中已經(jīng)介紹過上圖中的多個功能按鈕了,這里再做一次統(tǒng)一的介紹。
view居中位置的幾種類型
類型及特點的對應(yīng)關(guān)系如下:
對齊方式的幾種類型
注意:只有選中多個view時,才能設(shè)置對齊方式
打包和伸展
- Pack 實在是沒看出有啥效果,如果你有發(fā)現(xiàn)請告知,謝謝
- Expand Horizontally 會根據(jù)你當(dāng)前view的約束條件的不同,以及當(dāng)前在水平方向是否有其他view 等得到不同的效果(Expand Vertically同理)
下圖中圈出來的這個就是 “Device in Editor”
Device in Editor
轉(zhuǎn)載請注明來自杭州安米通儀器設(shè)備有限公司,本文標(biāo)題:《android:ConstraintLayout 的使用》
還沒有評論,來說兩句吧...