原文:Constraintlayout basics create constraints 作者:Mark Allison
ConstraintLayout
的核心基礎(chǔ)就是創(chuàng)建約束。約束定義了布局內(nèi)兩個組件之間的關(guān)系,從而控制組件的布局位置。對于剛接觸 ConstraintLayout
但對 RelativeLayout
熟悉的開發(fā)者來說,約束布局的工作原理很像 RelativeLayout
中通過創(chuàng)建組件間關(guān)系來控制布局。
最容易創(chuàng)建約束布局的方式是通過 Android Studio 中的 design
可視化布局編輯器。本文章的例子都通過藍圖 Blueprint
視圖來查看展示,我們先簡單看看在 Blueprint
視圖中的 TextView
。
清晰地可以看到 TextView
組件,以及兩個箭頭符號表示在這個 TextView
組件上存在約束將它對齊到父組件 ConstraintLayout
的左邊緣和上邊緣。待會再來看它們是如何創(chuàng)建的,還可以看到存在 16dp 的外邊距讓父組件 ConstraintLayout
和 TextView
的組件邊緣之間保留了一些間隙。選擇 TextView
組件就會看到如下的縮放和約束錨點。
邊角上的小正方形是縮放的控制點,通過拖拉這些點就可以對 TextView
進行縮放。但是這個大多數(shù)情況并不是很適用,因為使用這種方式進行縮放后的組件將保持固定的尺寸,而我們往往更需要 TextView
根據(jù)具體情況響應(yīng)式大小。
每條邊中間的錨點就是約束錨點,我們就是用這個錨點來創(chuàng)建約束的。其中左邊和上邊的錨點里面有藍點表示這個錨點已經(jīng)存在了一個約束,相對的右邊和下邊的空心錨點則表示沒有約束。從這個例子,我們就可以看到 TextView
的布局位置就通過定義約束來對齊了父組件。
任何繼承了 TextView
的子組件都擁有另一個錨點:被稱為基線(baseline)。這就允許我們通過該錨點來調(diào)整組件內(nèi)的文字對齊基線。選擇 TextView
后出現(xiàn)下方按鈕,點擊其中的 ab
按鈕來顯示這個錨點。
在 TextView
上出現(xiàn)香腸狀的控制錨點就是基線約束錨點。我們可以通過給這個錨點添加約束就像下面提到給四個邊的約束錨點添加約束一樣。
另一個出現(xiàn)的下方按鈕中是取消約束按鈕(按鈕中存在 'x' ),點擊將移除該組件上的所有約束。
創(chuàng)建錨點,我們只需要簡單的從一個組件的錨點,拖動指向到另一個組件 View
的錨點。此處的例子,我們創(chuàng)建另一個 TextView
(id 為 textView2
,原來的那個 id 是 textview
),而且 textView2
已有一個對齊父組件左邊的約束,我們再創(chuàng)建一個約束,從 textView2
的上邊到 textview
的下邊。而這個約束就會讓 textView2
對齊到 textview
正下方,如下所示:
在此處還要注意,我們創(chuàng)建的約束是從 textView2
的上邊到 textView
的下邊,當(dāng)我們選擇這兩個組件的時候,我們只會看到 textView2
的上邊約束錨點存在約束,而 textView
的下邊約束錨點是空心的不存在約束。
這樣的原因是約束是單向的(除非我們談?wù)摰募s束是鏈接 chains ),所以這里例子創(chuàng)建的約束是屬于 textView2
的,影響的也是 textView2
的布局位置是相對于 textView
的。因為該約束是只屬于 textView2
的,反過來不會影響 textView
的布局位置
上面講到的是同級組件間創(chuàng)建約束,而對于一個組件要創(chuàng)建相對于父組件的約束,則只是簡單的將約束拖的方向到合適的父組件邊緣即可,如下:
對于想了解在可視化布局下真正的存儲的是如何的開發(fā)者,以下就是 上面例子的 XML 源碼:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="TextView" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:text="TextView" />
</android.support.constraint.ConstraintLayout>
代碼中的約束都是以 app:layout_constraint
開頭的屬性。我們可以看到 ConstraintLayout
中所有子組件都存在這些屬性。讓他們對齊父組件的邊緣。你還可以看到 textView2
定義了一個約束聲明了該組件的上邊相對對齊到 textview
的下邊。
值得一提的是,這些屬性設(shè)置都是使用的 app
命名空間因為 ConstraintLayout
是像 Support libraries
也是作為庫引入。它屬于你的命名空間 app
而不是屬于安卓框架(使用命名空間 android
)。
上面提到我們可以通過選中組件后出現(xiàn)的清空按鈕來清除所有的約束。最后,我們還要介紹的是只刪除其中一個約束。如果在 XML 源碼中可以直接去掉相應(yīng)的屬性。若使用的是可視化編輯器,則通過點擊約束錨點來去除約束條件。
更多建議: