使用 ConstraintLayout 打造回應式 UI Android Jetpack 的一部分。
ConstraintLayout 可讓您使用平面檢視區塊階層建立複雜的大型版面配置,而不必使用巢狀檢視區塊群組。這與 RelativeLayout 類似,因為所有檢視區塊都是根據同層級檢視區塊和上層布局之間的關係配置,但比 RelativeLayout 更具彈性,且更容易與 Android Studio 的版面配置編輯器搭配使用。
版面配置 API 和版面配置編輯器是專為彼此打造,因此您可以直接透過版面配置編輯器的視覺化工具,使用 ConstraintLayout 的所有功能。您可以完全透過拖曳方式建構 ConstraintLayout 版面配置,不必編輯 XML。
本頁面說明如何在 Android Studio 3.0 以上版本中,使用 ConstraintLayout 建構版面配置。如要進一步瞭解版面配置編輯器,請參閱「使用版面配置編輯器打造 UI」。
如要查看可使用 ConstraintLayout 建立的各種版面配置,請參閱 GitHub 上的 Constraint Layout Examples 專案。
限制總覽
如要在 ConstraintLayout 中定義檢視區塊的位置,請為檢視區塊新增至少一個水平和一個垂直限制條件。每項限制條件代表與其他檢視畫面、上層布局或隱形指南的連接或對齊方式。每項限制都會定義檢視區塊在垂直或水平軸上的位置。每個檢視區塊的每個軸至少要有一個限制,但通常需要更多限制。
將檢視區塊拖曳至版面配置編輯器時,即使沒有限制,檢視區塊也會停留在您放置的位置。這只是為了方便編輯。如果在裝置上執行版面配置時,檢視區塊沒有限制,系統會將其繪製在 [0,0] 位置 (左上角)。
在圖 1 中,版面配置在編輯器中看起來不錯,但檢視區塊 C 沒有垂直限制。這個版面配置在裝置上繪製時,檢視區塊 C 會與檢視區塊 A 的左右邊緣水平對齊,但由於沒有垂直限制,因此會顯示在螢幕頂端。
圖 1. 編輯器會在 A 下方顯示檢視區塊 C,但沒有垂直限制。
圖 2. 檢視畫面 C 現在垂直受限於檢視畫面 A 下方。
雖然缺少限制不會導致編譯錯誤,但版面配置編輯器會在工具列中將缺少限制標示為錯誤。如要查看錯誤和其他警告,請按一下「顯示警告和錯誤」
。為避免遺漏限制,版面配置編輯器會使用自動連結和推斷限制功能,自動為您新增限制。
將 ConstraintLayout 新增至專案
如要在專案中使用 ConstraintLayout,請按照下列步驟操作:
- 請確保您在
settings.gradle檔案中宣告了maven.google.com存放區:Groovy
dependencyResolutionManagement { ... repositories { google() } )
Kotlin
dependencyResolutionManagement { ... repositories { google() } }
- 在模組層級的
build.gradle檔案中,將程式庫新增為依附元件,如下列範例所示。最新版本可能與範例中顯示的版本不同。Groovy
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
- 在工具列或同步通知中,按一下「Sync Project with Gradle Files」。
現在可以開始使用 ConstraintLayout 建構版面配置。
轉換版面配置
圖 3. 要轉換為的版面配置選單 ConstraintLayout。
如要將現有的版面配置轉換為限制條件版面配置,請按照下列步驟操作:
- 在 Android Studio 中開啟版面配置,然後按一下編輯器視窗底部的「Design」分頁標籤。
- 在「Component Tree」(元件樹狀結構) 視窗中,在版面配置上按一下滑鼠右鍵,然後按一下「Convert LinearLayout to ConstraintLayout」(將 LinearLayout 轉換為 ConstraintLayout)。
建立新的版面配置
如要開始使用新的限制式版面配置檔案,請按照下列步驟操作:
- 在「Project」視窗中,按一下模組資料夾,然後依序選取「File」>「New」>「XML」>「Layout XML」。
- 輸入版面配置檔案的名稱,然後在「Root Tag」中輸入「androidx.constraintlayout.widget.ConstraintLayout」。
- 按一下「Finish」。
新增或移除限制
如要新增限制,請按照下列步驟操作:
影片 1. 檢視畫面的左側會限制在父項的左側。
將檢視畫面從「Palette」視窗拖曳至編輯器。
在
ConstraintLayout中新增檢視區塊時,系統會以定界框顯示該檢視區塊,且每個角落都有正方形的調整大小控點,每一側則有圓形的限制控點。- 按一下要選取的檢視畫面。
- 執行下列任一操作:
- 按一下限制控點,然後拖曳至可用的錨點。 這個點可以是另一個檢視區塊的邊緣、版面配置的邊緣或參考線。請注意,拖曳限制控點時,版面配置編輯器會顯示潛在的連結錨點和藍色疊加層。
在「Attributes」視窗的「Layout」部分中,按一下「Create a connection」按鈕
,如圖 4 所示。
圖 4. 「屬性」視窗的「版面配置」部分可讓您建立連線。
建立限制條件時,編輯器會提供預設邊界,分隔兩個檢視區塊。
建立限制時,請遵守下列規則:
- 每個檢視區塊都必須至少有兩個限制條件:一個水平和一個垂直。
- 您只能在共用同一平面的限制控點和錨點之間建立限制。檢視區塊的垂直平面 (左側和右側) 只能限制為另一個垂直平面,而基準線只能限制為其他基準線。
- 每個限制控點只能用於一個限制,但您可以從不同檢視區塊建立多個限制,並指向同一個錨點。
如要刪除限制,請採取下列任一做法:
- 按一下要選取的限制,然後點選「Delete」(刪除)。
按住 Control 鍵 (在 macOS 上為 Command 鍵) 並使用滑鼠點選限制錨點。如圖 5 所示,限制條件會變成紅色,表示您可以點按刪除。
圖 5. 紅色限制表示可以點選刪除。
在「屬性」視窗的「版面配置」部分,按一下限制錨點,如圖 6 所示。
圖 6. 按一下要刪除的限制錨點。
影片 2. 新增與現有限制條件相反的限制條件。
如果您在檢視區塊中加入相反的限制,限制線會像彈簧一樣捲曲,表示相反的作用力,如影片 2 所示。如果檢視區塊大小設為「固定」或「包裝內容」,效果最為明顯,此時檢視區塊會置中顯示在限制之間。如果希望檢視區塊將大小延展至符合限制條件,請將大小切換為「符合限制條件」。如要保留目前大小,但移動檢視區塊,使其不要置中,請調整限制偏差。
如要達成不同類型的版面配置行為,可以使用限制,如下列章節所述。
父項位置
將檢視畫面的側邊限制在版面配置的對應邊緣。
在圖 7 中,檢視畫面的左側會連結至上層布局的左側邊緣。你可以使用邊界定義與邊緣的距離。
圖 7. 父項的水平限制。
訂單位置
定義兩個檢視區塊的顯示順序,可以是垂直或水平。
在圖 8 中,B 受限於一律位於 A 的右側,而 C 則受限於 A 的下方。不過,這些限制並不代表對齊,因此 B 仍可上下移動。
圖 8. 水平和垂直限制條件。
對齊
將一個檢視畫面的邊緣對齊另一個檢視畫面的邊緣。
在圖 9 中,B 的左側與 A 的左側對齊。如要對齊檢視區塊中心,請在兩側建立限制。
您可以從限制條件向內拖曳檢視區塊,藉此偏移對齊方式。 舉例來說,圖 10 顯示 B 的偏移對齊為 24dp。位移是由受限檢視區塊的邊界定義。
您也可以選取要對齊的所有檢視畫面,然後按一下工具列中的「對齊」
,選取對齊類型。
圖 9.水平對齊限制條件。
圖 10. 偏移水平對齊限制條件。
基準線對齊
將檢視區塊的文字基準線對齊另一個檢視區塊的文字基準線。
在圖 11 中,B 的第一行與 A 中的文字對齊。
如要建立基準限制,請在要限制的文字檢視區塊上按一下滑鼠右鍵,然後按一下「Show Baseline」(顯示基準)。然後按一下文字基準線,並將線條拖曳到其他基準線。
圖 11. 基準對齊限制。
只沿著參考線移動
您可以新增垂直或水平參考線,限制檢視區塊,且應用程式使用者看不到這些參考線。您可以根據 dp 單位或相對於版面配置邊緣的百分比,將參考線放置在版面配置內。
如要建立輔助線,請按一下工具列中的「輔助線」
,然後點選「新增垂直輔助線」或「新增水平輔助線」。
拖曳虛線即可重新放置,點選輔助線邊緣的圓圈即可切換測量模式。
圖 12. 受引導線限制的檢視區塊。
限制在障礙物內
與輔助線類似,障礙是可限制檢視區塊的隱形線,但障礙不會定義自己的位置。而是根據所含檢視區塊的位置移動。如果您想將檢視區塊限制為一組檢視區塊,而非一個特定檢視區塊,這項功能就非常實用。
舉例來說,在圖 13 中,檢視區塊 C 會限制在障礙的右側。障礙會設為檢視畫面 A 和檢視畫面 B 的「結尾」(或從左到右版面配置中的右側)。障礙會根據檢視畫面 A 或檢視畫面 B 的右側是否最右側而移動。
如要建立障礙,請按照下列步驟操作:
- 依序點選工具列中的「格線」
「新增垂直格線」或「新增水平格線」。 - 在「Component Tree」視窗中,選取要放在屏障內的檢視區塊,然後拖曳至屏障元件。
- 從「Component Tree」選取障礙,開啟「Attributes」
視窗,然後設定 barrierDirection。
現在您可以建立從另一個檢視區塊到障礙的限制條件。
您也可以將障礙內的檢視區塊限制在障礙內。這樣一來,即使您不知道哪個檢視區塊最長或最高,也能對齊障礙中的所有檢視區塊。
您也可以在障礙物內加入指引,確保障礙物達到「最低」位置。
圖 13. 檢視畫面 C 受限於障礙,會根據檢視畫面 A 和 B 的位置和大小移動。
調整限制偏差
如果您在檢視區塊的兩側都新增限制,且相同維度的檢視區塊大小為「固定」或「包裝內容」,則檢視區塊會預設以 50% 的偏差值置中於兩個限制之間。如要調整偏差,請在「屬性」視窗中拖曳偏差滑桿,或拖曳檢視畫面,如影片 3 所示。
如要讓檢視區塊將大小延展至符合限制條件,請將大小切換為「符合限制條件」。
影片 3. 調整限制偏差。
調整檢視畫面大小
圖 14. 選取檢視畫面時,「Attributes」視窗會包含以下控制項:1 尺寸比例、2 刪除限制、3 高度或寬度模式、4 邊界,以及5 限制偏差。您也可以在「6」限制清單中點選個別限制,在版面配置編輯器中醒目顯示這些限制。
您可以使用角落控點調整檢視區塊大小,但這樣會將大小硬式編碼,檢視區塊不會因內容或螢幕大小而調整大小。如要選取其他大小調整模式,請按一下檢視畫面,然後開啟編輯器右側的「屬性」
視窗。
「Attributes」視窗頂端附近是檢視檢查器,其中包含多個版面配置屬性的控制項,如圖 14 所示。這項功能僅適用於限制條件版面配置中的檢視區塊。
如要變更高度和寬度的計算方式,請按一下圖 14 中以註解 3 標示的符號。這些符號代表的大小模式如下。按一下符號,即可在下列設定之間切換:
-
固定:在下列文字方塊中指定特定尺寸,或在編輯器中調整檢視區塊大小。 -
包裝內容:檢視畫面只會在確實有需要時延伸,讓其與內容相符。 - layout_constrainedWidth
-
相符限制:檢視畫面會盡可能擴大,以符合各邊的限制,並考量檢視畫面的邊界。不過,您可以使用下列屬性和值修改該行為。只有在將檢視畫面寬度設為「符合限制」時,這些屬性才會生效:
- layout_constraintWidth_min
這會採用
dp維度,做為檢視區塊的最小寬度。 - layout_constraintWidth_max
這會採用檢視區塊最大寬度的
dp維度。
不過,如果指定維度只有一個限制,檢視畫面就會擴展以符合內容。在高度或寬度上使用這個模式,也能設定大小比例。
- layout_constraintWidth_min
將此值設為 true,讓水平維度變更為遵守限制。根據預設,設為 WRAP_CONTENT 的小工具不會受到限制。
將大小設為比率
圖 15. 檢視畫面會設為 16:9 的比例,寬度則會根據高度的比例設定。
如果至少一個檢視區塊尺寸設為「符合限制條件」圖示 0dp,您可以將檢視區塊大小設為比例,例如 16:9。如要啟用比例,請按一下「切換顯示比例限制」圖示 (圖 14 中的標註 1),然後在顯示的輸入欄位中輸入 width:height 比例。
如果寬度和高度都設為「配合限制」,您可以點按「切換長寬比限制」,選取要以其他維度的比例為依據的維度。檢視區塊檢查器會以實線連接對應邊緣,指出哪個維度設為比例。
舉例來說,如果將兩側都設為「符合限制」,請按兩下「切換長寬比限制」,將寬度設為高度的比例。整個大小取決於檢視區塊的高度,可透過任何方式定義,如圖 15 所示。
調整檢視邊界
如要讓檢視畫面間隔均等,請按一下工具列中的「邊界」
,然後選取要新增至版面配置的每個檢視畫面預設邊界。您對預設邊界所做的任何變更,只會套用至之後新增的檢視畫面。
如要控制每個檢視區塊的邊界,請在代表各項限制的行上按一下數字,即可在「屬性」視窗中進行設定。在圖 14 中,標註 4 顯示底邊界設為 16dp。
圖 16. 工具列的「邊界」按鈕。
工具提供的所有邊界都是 8dp 的倍數,可協助您將檢視區塊對齊質感設計的 8dp 方格網格建議。
使用鏈結控制線性群組
圖 17. 含有兩個檢視區塊的水平鏈結。
鏈結是藉由雙向位置限制條件互相連結的一組檢視畫面。鏈結中的檢視畫面可以垂直或水平分布。
圖 18. 各個鏈結樣式的範例。
你可以透過下列其中一種方式設定鏈結樣式:
- 分散:考量邊界後,平均分配檢視區塊。此為預設值。
- 內部間距:第一個和最後一個檢視區塊會固定在鏈結兩端的限制條件上,其餘檢視區塊則會平均分配。
- 加權:將鏈結設為「spread」或「spread inside」時,您可以將一或多個檢視畫面設為「match constraints」(
0dp),填滿剩餘空間。根據預設,系統會平均分配設為「match constraints」的每個檢視畫面之間的空間,但您可以使用layout_constraintHorizontal_weight和layout_constraintVertical_weight屬性,為每個檢視畫面指派重要性權重。這項屬性的運作方式與layout_weight線性版面配置中的相同:權重值最高的檢視區塊會取得最多空間,權重相同的檢視區塊則會取得相同空間。 - 封裝:系統會將檢視區塊封裝在一起,並考量邊界。如要調整整個鏈結的偏差 (向左或向右,或向上或向下),請變更鏈結的「頭」檢視區塊偏差。
鏈結的「頭」檢視區塊 (水平鏈結中最左側的檢視區塊,以及垂直鏈結中最頂端的檢視區塊) 會在 XML 中定義鏈結的樣式。不過,您可以選取鏈結中的任一檢視畫面,然後點選檢視畫面下方顯示的鏈結按鈕
,在「展開」、「展開內部」和「封裝」之間切換。
如要建立鏈結,請按照影片 4 所示操作:
- 選取要納入鏈結的所有檢視畫面。
- 在其中一個檢視區塊上按一下滑鼠右鍵。
- 選取「連鎖店」。
- 選取「水平置中」或「垂直置中」。
影片 4. 建立水平鏈結。
使用鏈結時,請注意以下幾點:
- 檢視區塊可以同時屬於水平和垂直鏈結,因此您可以建構彈性的格狀版面配置。
- 如圖 14 所示,只有在鏈結的兩端都限制在同一軸上的另一個物件時,鏈結才能正常運作。
- 雖然鏈結的方向是垂直或水平,但使用其中一個方向不會對齊該方向的檢視區塊。如要讓鏈結中的每個檢視區塊都位於正確位置,請加入其他限制,例如對齊限制。
自動建立限制
您不必在版面配置中放置檢視區塊時,為每個檢視區塊新增限制,只要將每個檢視區塊移至版面配置編輯器中的所需位置,然後按一下「推斷限制」
,系統就會自動建立限制。
「推斷限制」會掃描版面配置,為所有檢視畫面找出最有效的限制條件組合。這項功能可將檢視區塊限制在目前位置,同時提供彈性。您可能需要進行調整,讓版面配置配合不同螢幕大小和螢幕方向做出預期回應。
「Autoconnect to Parent」(自動連結上層版面) 是可啟用的獨立功能。啟用這項功能後,當您將子項檢視區塊新增至父項時,系統會自動為每個檢視區塊建立兩個以上的限制,但前提是將檢視區塊限制在父項版面配置中是適當的做法。Autoconnect 不會建立版面配置中其他檢視區塊的限制。
自動連線功能預設為停用。按一下版面配置編輯器工具列中的「Enable Autoconnection to Parent」(啟用自動連結上層版面功能)
,即可啟用這項功能。
主要畫面格動畫
在 ConstraintLayout 中,您可以使用 ConstraintSet 和 TransitionManager,為元素的大小和位置變更製作動畫。
ConstraintSet 是輕量型物件,代表 ConstraintLayout 中所有子項元素的限制、邊界和邊框間距。對顯示的 ConstraintLayout套用 ConstraintSet 時,版面配置會更新所有子項的限制。
如要使用 ConstraintSet 建構動畫,請指定兩個版面配置檔案,做為動畫的開始和結束主要畫面格。接著,您可以從第二個關鍵影格檔案載入 ConstraintSet,並套用至顯示的 ConstraintLayout。
以下程式碼範例說明如何將單一按鈕移動到螢幕底部。
// MainActivity.kt
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.keyframe_one)
constraintLayout = findViewById(R.id.constraint_layout) // member variable
}
fun animateToKeyframeTwo() {
val constraintSet = ConstraintSet()
constraintSet.load(this, R.layout.keyframe_two)
TransitionManager.beginDelayedTransition()
constraintSet.applyTo(constraintLayout)
}
// layout/keyframe1.xml // Keyframe 1 contains the starting position for all elements in the animation // as well as final colors and text sizes. <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
// layout/keyframe2.xml // Keyframe 2 contains another ConstraintLayout with the final positions. <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
其他資源
ConstraintLayout 用於 Sunflower 試用版應用程式。