ConstraintLayout約束佈局使用指南

A ConstraintLayout是一個ViewGroup容許您以靈活的方式定位和調整小部件的方法。android

注意: ConstraintLayout做爲支持庫提供,您能夠在API級別9(Gingerbread)開始的Android系統上使用。所以,咱們計劃隨着時間的推移豐富其API和功能。app

您目前可使用各類類型的約束:ide

  • 相對定位
  • 邊距
  • 居中定位
  • 圓形定位
  • 可見性行爲
  • 尺寸限制
  • 虛擬助手對象
  • 優化

請注意,您不能在約束中具備循環依賴關係。佈局

Developer Guide

相對定位

相對定位是在ConstraintLayout中建立佈局的基本構建塊之一。這些約束容許您將給定的小部件相對於另外一個小部件進行定位。您能夠在水平和垂直軸上約束小部件:優化

  • 水平軸:左,右,起點和終點
  • 垂直軸:頂部,底部和文本基線

通常概念是將窗口小部件的給定側約束到任何其餘窗口小部件的另外一側。動畫

例如,爲了將按鈕B定位在按鈕A的右側(圖1):ui

圖1-相對定位示例

你須要這樣作:翻譯

<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
		app:layout_constraintLeft_toRightOf="@+id/buttonA" />

這告訴系統咱們但願按鈕B的左側被約束到按鈕A的右側。這樣的位置約束意味着系統將嘗試讓雙方共享相同的位置。3d

圖2 - 相對定位約束

如下是可用約束的列表(上圖):code

  • layout_constraintLeft_toLeftOf
  • layout_constraintLeft_toRightOf
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintBaseline_toBaselineOf
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

它們都引用id另外一個小部件,或者parent引用父容器,即ConstraintLayout:

<Button android:id="@+id/buttonB" ...
		app:layout_constraintLeft_toLeftOf="parent" />

邊距

圖3 - 相對定位邊距

若是設置了邊距,則它們將應用於相應的約束(若是存在)(上圖),將邊距強制爲目標和源邊之間的空間。一般的佈局邊距屬性可用於此效果:

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginLeft
  • android:layout_marginTop
  • android:layout_marginRight
  • android:layout_marginBottom

請注意,保證金只能是正數或等於零,而且須要a Dimension。

鏈接到GONE小部件時的邊距

當位置約束目標的可見性爲View.GONE,您還可使用如下屬性指示要使用的不一樣邊距值:

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

居中定位和偏壓

一個有用的方面ConstraintLayout是它如何處理「不可能」的約束。例如,若是咱們有相似的東西:

<android.support.constraint.ConstraintLayout ...>
	<Button android:id="@+id/button" ...
			app:layout_constraintLeft_toLeftOf="parent"
			app:layout_constraintRight_toRightOf="parent/>
</android.support.constraint.ConstraintLayout>

圖4 - 居中定位

在這種狀況下發生的事情是,約束的做用就像是相反的力量將小部件拉平(圖4); 這樣小部件最終將在父容器中居中。這一樣適用於垂直約束。

偏壓

遇到這種相反的約束時的默認設置是使窗口小部件居中; 可是您可使用誤差屬性調整定位以使一側偏向另外一側:

  • layout_constraintHorizontal_bias
  • layout_constraintVertical_bias

圖5 - 偏置定心定位

例如,如下將使左側具備30%的誤差而不是默認的50%,使得左側將更短,小部件更傾向於左側(如上圖):

<android.support.constraint.ConstraintLayout ...>
	<Button android:id="@+id/button" ...
			app:layout_constraintHorizontal_bias="0.3"
			app:layout_constraintLeft_toLeftOf="parent"
			app:layout_constraintRight_toRightOf="parent/>
</android.support.constraint.ConstraintLayout>

使用誤差,您能夠製做更好地適應屏幕尺寸變化的用戶界面。

循環定位(1.1中增長)

您能夠以角度和距離約束窗口小部件中心相對於另外一個窗口小部件中心。這容許您將小部件放在圓上(以下圖)。可使用如下屬性:

  • layout_constraintCircle :引用另外一個小部件ID
  • layout_constraintCircleRadius :到其餘小部件中心的距離
  • layout_constraintCircleAngle :小部件應該處於哪一個角度(以度爲單位,從0到360) 圖6 - 圓形定位圖6 - 圓形定位
<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
		app:layout_constraintCircle="@+id/buttonA"
		app:layout_constraintCircleRadius="100dp"
		app:layout_constraintCircleAngle="45" />

可見性行爲

ConstraintLayout具備標記爲小部件的特定處理View.GONE。

GONE像往常同樣,窗口小部件不會顯示,也不是佈局自己的一部分(即若是標記爲,它們的實際尺寸將不會更改GONE)。

但就佈局計算而言,GONE小部件仍然是其中的一部分,具備重要的區別:

  • 對於佈局傳遞,它們的尺寸將被視爲零(基本上,它們將被解析爲一個點)
  • 若是他們對其餘小部件有限制,他們仍然會受到尊重,但任何邊距都會等於零

圖7 - 可見性行爲

這種特定的行爲容許構建佈局,您能夠暫時將窗口小部件標記爲GONE,而不會破壞佈局(如上圖),這在進行簡單的佈局動畫時尤爲有用。

注意:使用的邊距將是B在鏈接到A時定義的邊距。在某些狀況下,這可能不是您想要的餘量(例如A在其容器側面有100dp的邊距,B只有16dp到A,A標記爲已消失,B將對容器有16dp的餘量)。所以,您能夠指定在鏈接到標記爲已消失的窗口小部件時要使用的備用邊距值(請參閱上面有關已刪除邊距屬性的部分)。

尺寸限制

ConstraintLayout上的最小尺寸

您能夠爲ConstraintLayout自身定義最小和最大尺寸:

  • android:minWidth 設置佈局的最小寬度
  • android:minHeight 設置佈局的最小高度
  • android:maxWidth 設置佈局的最大寬度
  • android:maxHeight 設置佈局的最大高度

ConstraintLayout當尺寸設置 爲時,將使用這些最小和最大尺寸WRAP_CONTENT。

小部件維度約束

能夠經過以3種不一樣方式設置android:layout_width和 android:layout_height屬性來指定小部件的維度:

  • 使用特定維度(文字值,例如123dp或Dimension參考)
  • 使用WRAP_CONTENT,這將要求小部件計算本身的大小
  • 使用0dp,至關於「 MATCH_CONSTRAINT」

圖8 - 尺寸約束

前兩個以與其餘佈局相似的方式工做。最後一個將以匹配所設置的約束的方式調整窗口小部件的大小(上圖,(a)是wrap_content,(b)是0dp)。若是設置了邊距,則在計算中將考慮它們(上圖,(c)中的0dp)。

重要提示: MATCH_PARENT不建議用於a中包含的小部件ConstraintLayout。能夠經過使用MATCH_CONSTRAINT設置爲相應的左/右或上/下約束來定義相似的行爲"parent"。

重要提示: MATCH_PARENT不建議用於a中包含的小部件ConstraintLayout。能夠經過使用MATCH_CONSTRAINT設置爲相應的左/右或上/下約束來定義相似的行爲"parent"。

WRAP_CONTENT:強制約束(在1.1中添加)

若是將維度設置爲WRAP_CONTENT,則在1.1以前的版本中,它們將被視爲文字維度 - 這意味着約束不會限制生成的維度。雖然一般這足夠(而且更快),但在某些狀況下,您可能但願使用WRAP_CONTENT,但仍然強制執行約束以限制生成的維度。在這種狀況下,您能夠添加一個相應的屬性:

  • app:layout_constrainedWidth=」true|false」
  • app:layout_constrainedHeight=」true|false」

MATCH_CONSTRAINT尺寸(在1.1中添加)

當維度設置爲時MATCH_CONSTRAINT,默認行爲是使結果大小佔用全部可用空間。還有幾個額外的修飾符:

  • layout_constraintWidth_min和layout_constraintHeight_min:將設置此維度的最小大小
  • layout_constraintWidth_max和layout_constraintHeight_max:將設置此維度的最大大小
  • layout_constraintWidth_percent和layout_constraintHeight_percent:將此維度的大小設置爲父級的百分比

最小和最大

爲min和max指示的值能夠是Dp中的維度,也能夠是「wrap」,它將使用與其相同的值WRAP_CONTENT。

百分比

要使用百分比,您須要設置如下內容:

  • 尺寸應設置爲MATCH_CONSTRAINT(0dp)
  • 默認值應設置爲百分比app:layout_constraintWidth_default="percent" 或app:layout_constraintHeight_default="percent"

(注意:這在1.1-beta1和1.1-beta2中是必需的,但若是定義了percent屬性,則在如下版本中不須要)

  • 而後將layout_constraintWidth_percent 或layout_constraintHeight_percent屬性設置爲0到1之間的值

比例

您還能夠將窗口小部件的一個維度定義爲另外一個維度的比率。爲此,您須要將至少一個約束維度設置爲0dp(即MATCH_CONSTRAINT),並將該屬性layout_constraintDimensionRatio設置爲給定比率。例如:

<Button android:layout_width="wrap_content"
		android:layout_height="0dp"
		app:layout_constraintDimensionRatio="1:1" />

將按鈕的高度設置爲與其寬度相同。

該比率可表示爲:

  • 浮點值,表示寬度和高度之間的比率
  • 「寬度:高度」形式的比率

若是兩個尺寸都設置爲MATCH_CONSTRAINT(0dp),您也可使用比率。在這種狀況下,系統設置知足全部約束的最大尺寸並保持指定的縱橫比。要根據另外一個特定邊的尺寸限制一個特定邊,能夠預先附加W,「或」 H,分別約束寬度或高度。例如,若是一個尺寸受兩個目標約束(例如,寬度爲0dp且以父節點爲中心),則能夠指示應該約束哪一邊,經過 在比率前添加字母W(用於約束寬度)或H(用於約束高度),用逗號分隔:

<Button android:layout_width="0dp"
		android:layout_height="0dp"
		app:layout_constraintDimensionRatio="H,16:9"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintTop_toTopOf="parent"/>

將按照16:9的比例設置按鈕的高度,而按鈕的寬度將匹配父項的約束。

鏈在單個軸(水平或垂直)上提供相似行的行爲。另外一個軸能夠獨立約束

建立一個鏈

若是一組小部件經過雙向鏈接連接在一塊兒,則它們被視爲鏈(參見圖9,顯示最小鏈,具備兩個小部件)。 圖9 - 鏈

鏈頭

鏈由鏈的第一個元素(鏈的「頭部」)上設置的屬性控制: 圖10 - 鏈頭

頭部是水平鏈的最左側小部件,垂直鏈的最頂部小部件。

鏈中的邊距

若是在鏈接上指定了邊距,則會考慮它們。在擴散鏈的狀況下,將從分配的空間中扣除保證金。

鏈式

設置屬性layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle鏈的第一個元素時,鏈的行爲將根據指定的樣式(默認值CHAIN_SPREAD)更改。

  • CHAIN_SPREAD - 元素將展開(默認樣式)
  • 加權連接CHAIN_SPREAD模式,若是設置了一些小部件MATCH_CONSTRAINT,它們將分割可用空間
  • CHAIN_SPREAD_INSIDE - 相似,但鏈的端點不會分散
  • CHAIN_PACKED - 鏈條的元素將被包裝在一塊兒。而後,子項的水平或垂直誤差屬性將影響打包元素的定位

圖11 - 鏈式樣式

加權鏈

鏈的默認行爲是在可用空間中平均分佈元素。若是使用了一個或多個元素MATCH_CONSTRAINT,它們將使用可用的空白空間(在它們之間平均分配)。屬性layout_constraintHorizontal_weight和layout_constraintVertical_weight 將控制如何將空間利用的元素之間進行分配MATCH_CONSTRAINT。例如,在包含兩個元素的鏈上使用MATCH_CONSTRAINT,第一個元素使用權重2,第二個元素使用權重1,第一個元素佔用的空間將是第二個元素佔用的空間的兩倍。

邊距和鏈條(1.1)

在鏈中的元素上使用邊距時,邊距是相加的。

例如,在水平鏈上,若是一個元素定義了10dp的右邊距而下一個元素定義了5dp的左邊距,則這兩個元素之間產生的邊距爲15dp。

在計算鏈用於定位項目的剩餘空間時,會同時考慮項目及其邊距。剩餘空間不包含邊距。

虛擬助手對象

除了以前詳述的內在功能外,您還可使用特殊的輔助對象ConstraintLayout來幫助您進行佈局。目前,該Guideline對象容許您建立相對於ConstraintLayout容器定位的水平和垂直指南。而後能夠經過將小部件約束到這樣的指導來定位小部件。在1.1中,Barrier也Group被添加了。

優化器(1.1)

在1.1中咱們暴露了約束優化器。您能夠經過將標記app:layout_optimizationLevel添加到ConstraintLayout元素來決定應用哪些優化。

  • none:未應用任何優化
  • 標準:默認。僅優化直接和障礙約束
  • 直接:優化直接約束
  • 障礙:優化障礙限制
  • 鏈:優化鏈約束(實驗)
  • 維度:優化維度度量(實驗),減小匹配約束元素的度量數量

此屬性是一個掩碼,所以您能夠經過列出所需的優化來決定打開或關閉特定的優化。例如:app:layout_optimizationLevel =「direct | barrier | chain」

使用心得

相較於RelativeLayout佈局,ConstraintLayout擁有更大的靈活性,對與減小布局的層級有很大的幫助:

例如,須要用到控件平分佈局的時候:

<android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/tv_sort_default"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="綜合"
            android:textColor="@color/colorAccent"
            android:textSize="@dimen/small_text"
            app:layout_constraintEnd_toStartOf="@+id/tv_sort_sales"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/toolbar"/>

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/tv_sort_sales"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="銷量"
            android:textColor="@color/middle_text"
            android:textSize="@dimen/small_text"
            app:layout_constraintEnd_toStartOf="@+id/tv_sort_price"
            app:layout_constraintStart_toEndOf="@+id/tv_sort_default"
            app:layout_constraintTop_toBottomOf="@id/toolbar"/>

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/tv_sort_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="價格"
            android:textColor="@color/middle_text"
            android:textSize="@dimen/small_text"
            app:layout_constraintEnd_toStartOf="@+id/tv_sort_filter"
            app:layout_constraintStart_toEndOf="@+id/tv_sort_sales"
            app:layout_constraintTop_toBottomOf="@id/toolbar"/>

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/tv_sort_filter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="篩選"
            android:textColor="@color/middle_text"
            android:textSize="@dimen/small_text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/tv_sort_price"
            app:layout_constraintTop_toBottomOf="@id/toolbar"/>

    </android.support.constraint.ConstraintLayout>

徹底不須要藉助於LinearLayout來實現。

後記

文章前邊都是Android官網上內容,能夠去官網查看原版,另外翻譯都是機器翻譯,只有少部分翻譯不恰當的更改了,若是形成閱讀障礙,請見諒!

相關文章
相關標籤/搜索