使用 ConstraintLayout 建構回應式 UI Android Jetpack 的一部分。

嘗試 Compose 方法
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中處理版面配置。

ConstraintLayout 可讓您使用平面檢視區塊階層建立複雜的大型版面配置,不使用巢狀檢視區塊群組。與 RelativeLayout 類似,所有檢視畫面都會根據同層級檢視畫面與上層版面配置之間的關係配置,但比 RelativeLayout 更有彈性,也更容易與 Android Studio 的版面配置編輯器搭配使用。

版面配置編輯器的視覺工具都提供 ConstraintLayout 的所有功能,因為版面配置 API 和版面配置編輯器是彼此特別建構的。您可以使用 ConstraintLayout 完全拖曳即可建立版面配置,不必編輯 XML。

本頁說明如何在 Android Studio 3.0 以上版本中使用 ConstraintLayout 建立版面配置。如要進一步瞭解版面配置編輯器,請參閱「使用版面配置編輯器打造 UI」。

如要查看可使用 ConstraintLayout 建立的多種版面配置,請參閱 GitHub 上的限製版面配置範例專案

限制總覽

如要在 ConstraintLayout 中定義檢視畫面的位置,請為檢視區塊新增至少一個水平和垂直限制條件。每項限制都代表與其他檢視畫面、上層版面配置或隱形指南的連結或對齊方式。每項限制都會定義檢視畫面的垂直或水平軸位置。每個檢視畫面的每一軸都必須有一個限制,但通常必須更多。

在版面配置編輯器中將檢視畫面拖曳到版面配置後,即使沒有任何限制,檢視畫面仍會保持原樣。這麼做是為了簡化編輯程序。在裝置上執行版面配置時,如果檢視畫面沒有任何限制,則繪製在位置 [0,0] (左上角)。

圖 1 中的版面配置看起來沒問題,但檢視畫面 C 沒有垂直限制。這個版面配置在裝置上繪圖時,檢視畫面 C 會水平對齊與檢視畫面 A 的左右邊緣,但由於沒有垂直限制,因此會顯示在螢幕頂端。

圖 1 編輯器會顯示 A 下方的檢視畫面 C,但沒有任何垂直限制。

圖 2. View C 現在垂直限制在檢視畫面 A 下方。

雖然缺少限制不會導致編譯錯誤,但版面配置編輯器會將缺少的限制顯示為工具列的錯誤。如要查看錯誤和其他警告,請按一下「Show Warnings and Errors」圖示 。為避免遺漏限制,版面配置編輯器會使用自動連線和推論限制功能,自動新增限制。

在專案中新增 ConstraintLayout

如要在專案中使用 ConstraintLayout,請按照下列步驟操作:

  1. 確認您已在 settings.gradle 檔案中宣告 maven.google.com 存放區:

    Groovy

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        )
        

    Kotlin

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        }
        
  2. 將程式庫新增為模組層級 build.gradle 檔案中的依附元件,如以下範例所示。最新版本可能與範例中顯示的內容不同。

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13")
    }
    
  3. 在工具列或同步通知中,按一下「Sync Project with Gradle Files」

現在可以使用 ConstraintLayout 建構版面配置。

轉換版面配置

圖 3. 將版面配置轉換為 ConstraintLayout 的選單。

如要將現有的版面配置轉換為限製版面配置,請按照下列步驟操作:

  1. 在 Android Studio 中開啟版面配置,然後按一下編輯器視窗底部的「Design」分頁標籤。
  2. 在「Component Tree」視窗中,在版面配置上按一下滑鼠右鍵,然後按一下「Convert LinearLayout to ConstraintLayout」。

建立新的版面配置

如要建立新的限製版面配置檔案,請按照下列步驟操作:

  1. 在「Project」視窗中,按一下模組資料夾,然後依序選取「File」>「New」>「XML」>「Layout XML」
  2. 輸入版面配置檔案名稱,然後在「Root Tag」中輸入「androidx.constraintlayout.widget.ConstraintLayout」。
  3. 按一下「Finish」

新增或移除限制

如要新增限制條件,請按照以下步驟操作:

影片 1. 檢視畫面的左側會限制在父項的左側。

  1. 將「Palette」視窗中的檢視畫面拖曳至編輯器中。

    ConstraintLayout 中新增檢視畫面後,畫面會在定界框中顯示,且每個角落都有方形大小調整控點,每邊都有圓形限制控點。

  2. 按一下並選取檢視畫面。
  3. 執行下列其中一項操作:
    • 按一下限制控點,然後拖曳至可用的錨點。這個點可以是其他檢視畫面的邊緣、版面配置的邊緣,或是引導線。請注意,拖曳限制控點時,版面配置編輯器會顯示可能的連線錨點和藍色疊加層。
    • 在「Attributes」視窗的「Layout」部分中,按一下其中一個「Create a connection」按鈕,如圖 4 所示。

      圖 4. 「Attributes」視窗的「Layout」區段可讓您建立連線。

限制建立後,編輯器會提供預設邊界來分隔兩個檢視畫面。

建立限制時,請記住下列規則:

  • 每個檢視畫面都必須有至少兩個限制:一個水平和一個垂直方向。
  • 您只能在限制控制代碼和共用相同平面的錨點之間建立限制。檢視畫面的左側和右側垂直平面只能限制在其他垂直平面上,基準線只能限制至其他基準。
  • 每個限制控點只能用於一項限制,但您可以從不同檢視畫面建立多項限制,並指向同一個錨點。

您可以透過下列任一方式刪除限制:

  • 按一下限制加以選取,然後點選「Delete」
  • 按住 Control 鍵 (在 macOS 上為 Command 鍵) 或限制錨點。限制會變成紅色,表示只要按一下即可刪除,如圖 5 所示。

    圖 5. 紅色限制條件表示只要按一下即可刪除。

  • 在「Attributes」視窗的「Layout」區段中,按一下限制錨點,如圖 6 所示。

    圖 6. 按一下限制錨點即可刪除。

影片 2.新增反對現有限制。

如果您在檢視畫面上加入相反的限制條件,限制線就會像彈跳一樣,表示相反的力量,如影片 2 所示。當檢視畫面大小設為「固定」或「包裝內容」時,效果最明顯,在這種情況下,檢視畫面會於限制之間置中。如果您希望檢視畫面延展尺寸以符合限制,請切換大小為「符合限制條件」。如要保留目前大小,但移動檢視畫面不要置中,請調整限制偏誤

您可以使用限制來達成不同類型的版面配置行為,如以下各節所述。

上層位置

將檢視畫面的側邊限制在版面配置的對應邊緣。

在圖 7 中,檢視區塊的左側連線至父項版面配置的左側邊緣。您可以使用邊界來定義與邊緣之間的距離。

圖 7. 父項的水平限制。

訂單位置

定義兩個檢視畫面的外觀順序 (垂直或水平)。

在圖 8 中,B 限制一律位於 A 右側,C 則限制在 A 以下。不過,這些限制並不代表對齊,因此 B 仍可上下移動。

圖 8. 水平和垂直限制條件。

切合需求

將檢視畫面的邊緣對齊另一個檢視畫面的相同邊緣。

在圖 9 中,B 的左側與 A 的左側對齊。如要對齊檢視畫面中心,請在兩側建立限制。

將檢視畫面從限制往內拖曳,即可調整對齊方式。例如,圖 10 以 24dp 偏移對齊的方式顯示 B。偏移量是由受限的檢視畫面邊界定義。

您也可以選取所有要對齊的檢視畫面,然後按一下工具列中的「Align」 來選取對齊類型。

圖 9.水平對齊限制。

圖 10.偏移水平對齊限制條件。

基準對齊

將不同檢視畫面的文字基準線對齊其他檢視畫面的文字基準線。

在圖 11 中,B 的第一行與 A 中的文字對齊。

如要建立基準限制,請在要限制的文字檢視區塊上按一下滑鼠右鍵,然後點選「Show Baseline」。接著,按一下文字基準線,然後將線條拖曳至其他基準線。

圖 11. 基準對齊限制。

限制準則

您可以新增垂直或水平引導線,用來限制檢視畫面,且應用程式使用者無法看見。您可以根據 dp 單位或相對於版面配置邊緣的百分比,在版面配置中放置引導線。

如要建立引導線,請按一下工具列中的「Guidelines」圖示 ,然後按一下「Add Vertical Guideline」或「Add Horizontal Guideline」

請拖曳虛線來調整位置,按一下引導線邊緣的圓圈,即可切換測量模式。

圖 12. 針對引導線限制的檢視畫面。

鎖定障礙物

與引導線類似,阻隔線是一種可以限制檢視畫面的隱形線,差別在於障礙不會定義自身的位置。而是會根據其中所含檢視畫面的位置移動。如果您想將檢視畫面限制為一組檢視畫面,而非只侷限於單一特定檢視畫面,這項功能就非常實用。

例如,在圖 13 檢視畫面 C 中,限制在障礙的右側。阻隔線會設為檢視畫面 A 和檢視畫面 B 的「結束」(或右側為右側版面配置)。障礙物的移動方式取決於檢視畫面 A 或檢視畫面 B 最右側。

如要建立障礙,請按照下列步驟操作:

  1. 按一下工具列中的「Guidelines」圖示 ,然後按一下「Add Vertical Barrier」或「Add Horizontal Barrier」
  2. 在「Component Tree」(元件樹狀結構) 視窗中,選取要在阻隔器內部的檢視區塊,並拖曳至阻隔元件中。
  3. 從「Component Tree」中選取阻隔線,開啟「Attributes」視窗,然後設定「barrierDirection」。

您現在可以建立從其他檢視畫面到阻隔線的限制。

您也可以將障礙物「內」的檢視畫面限制為障礙。如此一來,即使您不知道哪個檢視畫面最長或最高,仍然可以讓阻斷層中的所有檢視畫面相互對齊。

您也可以在阻隔線內加入引導線,確保「最小」障礙對應的位置。

圖 13. 檢視畫面 C 受限於障礙物,而阻礙會依據檢視畫面 A 和檢視畫面 B 的位置和大小移動。

調整限制偏誤

如果您在檢視畫面的兩端新增限制,且相同維度的檢視畫面大小為「固定」或「包裝內容」,檢視畫面會在兩個限制之間預設為中心點,偏誤為 50%。如要調整偏誤,請在「Attributes」視窗中拖曳偏誤滑桿,或是拖曳檢視畫面,如影片 3 所示。

如果您希望檢視畫面能依據限制條件彈性調整大小,請切換大小為「符合限制條件」。

影片 3:調整限制偏誤。

調整檢視畫面大小

圖 14. 選取檢視畫面時,「Attributes」視窗會顯示下列控制項:1 種大小比例、2刪除限制、3 個高度或寬度模式、4 個邊界,以及「5」限制自訂調整。您也可以點選 6 限制清單中的個別限制,在版面配置編輯器中醒目顯示。

您可以使用邊角控點調整檢視畫面大小,但此硬式編碼會寫入大小,檢視畫面不會根據不同內容或螢幕大小調整大小。如要選取其他大小模式,請點選某個檢視畫面,然後開啟編輯器右側的「Attributes」 視窗。

「Attributes」視窗頂端附近是檢視畫面檢查器,其中包含數個版面配置屬性的控制項,如圖 14 所示。這項功能僅適用於限製版面配置中的檢視畫面。

按一下圖 14 中附有摘要 3 的符號,即可變更高度和寬度的計算方式。這些符號代表大小模式,如下所示。按一下符號即可切換這些設定:

  • 固定:請在下列文字方塊中指定特定尺寸,或在編輯器中調整檢視畫面大小。
  • 納入內容:檢視畫面只會根據內容進行適當展開。
    • layout_constraintWidth
    • 設為 true 即可讓水平維度變更,使其符合限制條件。根據預設,設為 WRAP_CONTENT 的小工具不受限制限制。

  • 比對限制:在計算檢視畫面邊界後,檢視畫面會盡可能展開以符合每一側的限制。不過,您可以使用下列屬性和值修改該行為。只有在您將檢視畫面寬度設為「比對限制」時,這些屬性才會生效:
    • layout_constraintWidth_min

      這會使用 dp 尺寸做為檢視區塊的最小寬度。

    • layout_constraintWidth_max

      這會使用 dp 尺寸做為檢視區塊的最大寬度。

    不過,如果指定維度只有一個限制,檢視畫面就會展開以符合內容。針對高度或寬度使用這個模式,也可以讓您設定大小比例

將大小設為比率

圖 15.檢視畫面設為 16:9 的顯示比例,根據高度的比例寬度。

如果至少有一項檢視維度設為「相符限制」(0dp),您可以將檢視畫面大小設為比例,例如 16:9。如要啟用比例,請按一下「Toggle Aspect Ratio Constraint」 (圖 14 中的圖標 1),然後在顯示的輸入中輸入 width:height 比例。

如果寬度和高度都設為「matchconstraint」,可以按一下「Toggle Aspect Ratio Constraint」,選取根據另一個比例的維度。檢視檢查器會將對應的邊緣與實線連結,藉此指出哪個維度設定為比例。

舉例來說,如果您將兩側的邊設為「符合限制」,請按一下「Toggle Aspect Ratio Constraint」兩次,將寬度設為高度的比例。整個大小取決於檢視畫面的高度,可任何方式定義,如圖 15 所示。

調整檢視邊界

如要讓檢視畫面平均間距,請按一下工具列中的「邊界」圖示 ,為每個新增至版面配置的檢視畫面選取預設邊界。您對預設邊界所做的任何變更,只會套用至之後新增的檢視畫面。

您可以按一下代表各項限制的行上的數字,在「Attributes」視窗中控制每個檢視畫面的邊界。在圖 14 中,呼叫 4 顯示下邊界設定為 16dp。

圖 16.工具列中的「邊界」按鈕。

工具提供的所有邊界都是 8dp 的係數,可協助您的檢視畫面對齊質感設計的 8dp 正方形格線建議。

使用鏈結控制線性團體

圖 17. 有兩個檢視畫面的水平鏈結。

鏈結是藉由雙向位置限制彼此連結的一組檢視畫面。鏈結中的檢視畫面可以垂直或水平分佈。

圖 18. 各個鏈結樣式的範例。

鏈結可採用下列任一樣式:

  1. 分散:系統會在計算邊界後平均分配檢視畫面。此為預設值。
  2. 分散內部:第一個和最後一個檢視畫面會附加至鏈結兩端的限制,其餘檢視畫面則平均分配。
  3. 加權:當鏈結設為「分散」或「散佈內部」時,您可以將一或多個檢視畫面設為「符合限制」(0dp),藉此填滿剩餘空間。根據預設,空間會平均分配給每個設為「比對限制條件」的檢視畫面,但您可以使用 layout_constraintHorizontal_weightlayout_constraintVertical_weight 屬性,為每個檢視畫面指派重要性權重。運作方式與線性版面配置中的 layout_weight 相同:最高權重值的檢視畫面會取得最多空間,而權重相同的檢視畫面會獲得相同數量的空間。
  4. 已封裝:系統在計算邊界後會封裝檢視畫面。您可以變更整個鏈結的偏誤 (向左、向右或向下),也可以變更鏈結的「頭部」視角偏誤。

鏈結的「頭部」檢視畫面是指水平鏈結 (在左至右版面配置中) 最左側的檢視畫面,以及垂直鏈中最上方的檢視畫面,在 XML 中定義鏈結的樣式。不過,您可以選取鏈結中的任何檢視畫面,然後按一下顯示在檢視畫面下方的鏈結按鈕 ,即可在「spread」、「spread in」 和「packed」之間切換。

如要建立鏈結,請執行下列操作,如影片 4 所示:

  1. 選取要納入鏈結的所有檢視畫面。
  2. 在其中一個檢視畫面上按一下滑鼠右鍵。
  3. 選取「Chains」
  4. 選取「置中水平」或「垂直置中」。

影片 4.建立水平鏈結。

使用鏈結時,請注意下列事項:

  • 檢視畫面可以是水平和垂直鏈結的一部分,方便您建構靈活的格線版面配置。
  • 鏈結的每一端限制為同一軸上的其他物件時,鏈結才能正常運作,如圖 14 所示。
  • 雖然鏈結的方向為垂直或水平,但使用其中一個無法將檢視畫面往該方向對齊。如要針對鏈結中每個檢視畫面的正確位置,請加入其他限制,例如對齊限制

自動建立限制

在版面配置中放入每個檢視畫面時,不必為每個檢視畫面新增限制,只要在版面配置編輯器中將每個檢視畫面移到所需位置,然後按一下「Infer Constraints」圖示 ,即可自動建立限制。

「Infer Constraints」(推論限制) 會掃描版面配置,找出所有檢視畫面最有效的一組限制條件。可將檢視畫面限制於其目前位置,同時提供彈性。您可能需要進行調整,讓版面配置能夠回應不同的螢幕大小和方向。

「自動連線到家長」是一項你可以啟用的獨立功能。如果啟用這項設定,並將子檢視畫面新增至父項,這項功能就會在您將子檢視畫面加入版面配置時,自動為每個檢視畫面建立兩個或以上的限制,但前提是必須將檢視畫面限製到上層版面配置。自動連線功能不會為版面配置中的其他檢視畫面設定限制。

自動連線功能預設為停用。按一下版面配置編輯器工具列中的「Enable Autoconnection to Parent」(啟用自動連結上層版面功能) 即可啟用。

主要畫面格動畫

ConstraintLayout 中,您可以使用 ConstraintSetTransitionManager,為元素大小和位置變更加入動畫效果。

ConstraintSet 是輕量型物件,代表 ConstraintLayout 中所有子項元素的限制、邊界和邊框間距。將 ConstraintSet 套用至顯示的 ConstraintLayout 時,版面配置會更新其所有子項的限制。

如要使用 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 試用版應用程式。