使用 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. 現在檢視畫面 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 顯示的 B 的偏移度為 24dp。偏移值是由受限檢視區塊的邊界定義。

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

圖 9.水平對齊限制。

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

基準對齊

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

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

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

圖 11. 基準對齊限制。

限制符合準則

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

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

拖曳虛線即可調整其位置,按一下橫線邊緣的圓圈則可切換測量模式。

圖 12. 依據準則限制的檢視畫面。

克服障礙

障礙與準則類似,是一種隱形線條,可讓您限制檢視畫面,但障礙不會定義自己的位置。而是會依據當中的檢視畫面位置移動。如果您想將檢視畫面限制於一組檢視畫面,而非只為特定檢視畫面,這個做法就很實用。

例如,圖 13 的檢視畫面 C 限制在障礙物的右側。障礙會設為檢視畫面 A 和檢視畫面 B 的「end」(或由左至右的版面配置的「end」)。視檢視畫面 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. 選取檢視畫面時,「屬性」視窗會提供下列控制項: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 長寬比限制」兩次,即可將寬度設為高度的比例。整個大小取決於檢視畫面的高度,可透過任何方式定義,如圖 15 所示。

調整檢視邊界

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

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

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

工具提供的所有邊界都是 8dp 的係數,有助於檢視畫面對齊 Material Design 的 8dp 方格建議。

使用鏈結控制線性群組

圖 17. 具有兩個檢視區塊的水平鏈結。

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

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

連鎖店的樣式如下:

  1. Spread:在計算利潤後,觀看次數會平均分配。此為預設值。
  2. 在內部配置:第一個和最後一個檢視畫面會連結至鏈結中每一端的限制,其餘檢視畫面則平均分配。
  3. 加權:當鏈結設為「spread」或「spread」內,您可以將一或多個檢視畫面設為「比對限制」(0dp),藉此填滿剩餘的空間。根據預設,空間會平均分配給設為「相符限制」的每個檢視畫面,但您可以使用 layout_constraintHorizontal_weightlayout_constraintVertical_weight 屬性為每個檢視畫面指派重要性權重。運作方式與線性版面配置中的 layout_weight 相同:權重值最高的檢視畫面會取得最多空間,而權重相同的檢視畫面會取得相同大小的空間。
  4. 已封裝:系統在計算利潤後,就會一併封裝檢視畫面。您可以變更鏈結的「頭」檢視區塊偏誤,調整整個鏈結的偏誤,包括左側、右側、向上或向下。

鏈結的「頭」檢視畫面 (橫向鏈結中最左側的檢視畫面) 和垂直鏈結中最頂端的檢視畫面,在 XML 中定義鏈結的樣式。不過,只要選取鏈結中的任一檢視畫面,然後按一下檢視畫面下方的鏈結按鈕 ,即可在「spread」、「spread 內部」和「已包裝」之間切換。

如要建立鏈結,請按照下列步驟操作,如影片 4 所示:

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

影片 4:建立水平鏈結。

使用鏈結時的注意事項如下:

  • 檢視區塊可以是水平和垂直鏈結的一部分,方便您建構彈性的格線版面配置。
  • 只有在鏈結的每一端都限制在同一軸上的另一個物件時,鏈結才能正常運作,如圖 14 所示。
  • 雖然鏈結的方向是垂直或水平,但使用其中一個無法對齊該方向的檢視畫面。如要達到鏈結中每個檢視畫面的正確位置,請納入其他限制,例如對齊限制

自動建立限制

您可以在版面配置編輯器中將每個檢視畫面移至所需位置,然後按一下「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 試用版應用程式。