使用 ConstraintLayout 打造回應式 UI Android Jetpack 的一部分。

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

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

版面配置編輯器的視覺工具可直接使用 ConstraintLayout 的所有功能,因為版面配置 API 和版面配置編輯器是特別為彼此打造。您可以透過拖曳 (而非編輯 XML) 來完全使用 ConstraintLayout 建構版面配置。

本頁說明如何在 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。偏移量是由受限檢視畫面的邊界定義。

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

圖 9. 水平對齊限制。

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

基準對齊

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

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

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

圖 11. 基準對齊限制。

限制相關規範

您可以新增垂直或水平引導線,藉此限制檢視畫面,避免應用程式使用者看到這些內容。您可以根據 dp 單位或相對於版面配置邊緣的百分比,在版面配置中放置引導線。

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

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

圖 12. 受到規範限制的檢視畫面。

限製造成阻礙

與引導線類似,阻隔線是可限制檢視畫面的隱形線條,但阻隔線並未定義自身的位置。而阻隔位置會根據其中所含檢視區塊位置移動。如果您想將檢視畫面限制為一組檢視畫面,而非特定檢視畫面,這項功能就非常實用。

例如,在圖 13 中,C 需限制在障礙右側。阻隔線會同時設為檢視畫面 A 和檢視畫面 B 的「end」(或右側由左至右版面配置)。分隔線會根據檢視畫面 A 右側或檢視畫面 B 的右側是最右側而移動。

如要建立阻隔線,請按照下列步驟操作:

  1. 按一下工具列中的「Guidelines」圖示 ,然後按一下「Add Vertical Barrier」(新增垂直障礙) 或「Add Horizontal Barrier」(新增水平障礙)
  2. 在「Component Tree」視窗中,選取想要的檢視畫面,並拖曳至阻隔線元件。
  3. 從「Component Tree」中選取阻隔線,開啟「Attributes」視窗,然後設定「barrierDirection」。

現在,您可以建立從另一個檢視畫面到阻礙點的限制。

您也可以限制受限於阻礙點的檢視畫面。這樣一來,即使您不知道哪個檢視畫面最長或最高,還是可以將障礙範圍內的所有檢視畫面對齊。

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

圖 13. View 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 的長寬比,並採用寬度的比例。

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

如果寬度和高度都設為「相符限制」,您可以按一下「Toggle Aspect Ratio Constraint」,根據兩者的比例來選取維度。檢視檢查器會將相應的邊緣與實心線連接,以指明尺寸設為比例。

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

調整檢視邊界

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

如要控制「Attributes」視窗中每個檢視畫面的邊界,請在代表每個限制的行上按一下數字。在圖 14 中,呼叫 4 顯示底部邊界已設為 16dp。

圖 16. 工具列的「Margin」按鈕。

工具提供的所有邊界都是 8dp 的因素,讓檢視畫面能符合 Material Design 的 8dp 方形格線建議。

使用鏈結控管線性群組

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

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

圖 18. 每種連鎖店樣式的範例。

您可透過下列任一方式設定鏈結的樣式:

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

鏈結的「head」檢視畫面 (水平鏈中最左邊的檢視畫面 (位於由左至右的版面配置) 和垂直鏈中最頂層的檢視畫面) 會在 XML 中定義鏈結的樣式。不過,只要選取鏈結中的任何檢視畫面,然後按一下顯示在檢視畫面下方的鏈結按鈕 ,即可在「spread」、「在內部使用」和「封裝」之間切換。

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

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

影片 4.建立水平鏈結。

使用鏈結時,請考量下列幾點:

  • 檢視區塊可以同時屬於水平和垂直鏈結,方便您建構彈性的格線版面配置。
  • 鏈結的每一端都必須繫結至同一軸上的另一個物件,才能正常運作,如圖 14 所示。
  • 雖然鏈結的方向是垂直或水平,但使用其中一個方向時,並不會依照該方向對齊檢視畫面。如要讓鏈結中的每個檢視畫面都顯示適當位置,請納入其他限制,例如對齊限制條件

自動建立限制

您可以在版面配置編輯器中將每個檢視畫面移至所需位置,然後按一下「Infer Constraints」 (推論限制),自動建立限制條件,而不必在版面配置中逐一新增限制。

推論限制會掃描版面配置,找出所有檢視區塊的最有效限制條件。這種模式會將檢視畫面限制在目前的位置,同時提供更多彈性。您可能需要進行調整,才能以您想要的不同螢幕大小和方向,對版面配置做出回應。

您可以啟用「自動連線至家長」這項獨立功能。如果啟用這項功能,且您會將子檢視畫面新增至父項,這項功能會在您將子檢視畫面新增至版面配置時,自動為每個檢視畫面建立兩個以上的限制,但只在適合將檢視畫面限制於父項版面配置時。Autoconnect 不會為版面配置中的其他檢視畫面建立限制。

自動連線功能預設為停用。按一下版面配置編輯器工具列中的「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 試用版應用程式。