ConstraintLayout 相對於 RelativeLayout來說性能更好,布局上也更加靈活。在最新的Google Android開發文檔中是推薦使用 ConstraintLayout的,下面來看看具體用法。
0x00 相對位置(Relative positioning)
這個比較簡單,看圖解釋,假設控件B要放在控件A的右側,可以使用 layout_constraintLeft_toRightOf屬性。


<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
app:layout_constraintLeft_toRightOf="@+id/buttonA" />
看圖2可以了解控件約束屬性代表的含義。


類似相對位置的約束屬性有:
layout_constraintLeft_toLeftOflayout_constraintLeft_toRightOflayout_constraintRight_toLeftOflayout_constraintRight_toRightOflayout_constraintTop_toTopOflayout_constraintTop_toBottomOflayout_constraintBottom_toTopOflayout_constraintBottom_toBottomOflayout_constraintBaseline_toBaselineOflayout_constraintStart_toEndOflayout_constraintStart_toStartOflayout_constraintEnd_toStartOflayout_constraintEnd_toEndOf
0x01 外邊距(Margins)
這個屬性也好理解,看圖3


可以通過以下屬性設置一個控件相對另一個控件的外邊距:
android:layout_marginStartandroid:layout_marginEndandroid:layout_marginLeftandroid:layout_marginTopandroid:layout_marginRightandroid:layout_marginBottom
屬性值必須是大於或者等於0。
接一下看一個 RelativeLayout 沒有的屬性:
0x02 Margins when connected to a GONE widget
當一個相對的控件隱藏時, ConstraintLayout也可以設置一個不同的邊距:
layout_goneMarginStartlayout_goneMarginEndlayout_goneMarginLeftlayout_goneMarginToplayout_goneMarginRightlayout_goneMarginBottom
具體的栗子下面會講到。
0x03 Centering positioning and bias
居中以及設置偏差


<android.support.constraint.ConstraintLayout ...> <Button android:id="@+id/button" ... app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout>
還可以設置bias屬性,表示子控件相對父控件的位置傾向,可以使用屬性:
layout_constraintHorizontal_biaslayout_constraintVertical_bias


假設設置控件A相對父控件橫向偏差是30%:
<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>
0x04 弧形定位(Circular positioning)
這個屬性是在1.1版本添加的。


可以使用屬性有:
layout_constraintCircle: 相對控件的idlayout_constraintCircleRadius: 相對控件中心的距離,也就是圓的半徑layout_constraintCircleAngle: 相對夾角 (從 0 ~ 360度)
例如,圖6代碼示例
<Button android:id="@+id/buttonA" ... /> <Button android:id="@+id/buttonB" ... app:layout_constraintCircle="@+id/buttonA" app:layout_constraintCircleRadius="100dp" app:layout_constraintCircleAngle="45" />
0x05 Visibility behavior


一般情況下,設置 GONE屬性后,控件就不會出現在布局中了,B控件對A控件的margin屬性也就沒有作用了。
但是 ConstraintLayout 能對已經設置 GONE屬性的控件進行特殊處理。當A控件設置 GONE之后,A控件相當於變成了一個點,B控件相對於對A的約束仍然是起作用的。圖7的代碼示例,A控件設置成了 GONE,當B控件的 margin屬性還是有作用的。
<android.support.constraint.ConstraintLayout ...>
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button A"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent" />
<!--當A控件設置Gone之后,B控件的margin屬性是起作用的,即左邊距還是30dp-->
<Button
android:id="@+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:text="button B"
app:layout_constraintLeft_toRightOf="@+id/buttonA" />
</android.support.constraint.ConstraintLayout>
然而有時候,B控件是不希望相對於隱藏控件的屬性還起作用。這時候可以用到上面0x02提到的 goneMargin屬性。
<android.support.constraint.ConstraintLayout ...>
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button A"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent" />
<!--當A控件設置Gone之后,希望B控件的左邊距為0dp,那么可以設置layout_goneMarginLeft屬性-->
<Button
android:id="@+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:text="button B"
app:layout_goneMarginLeft="0dp"
app:layout_constraintLeft_toRightOf="@+id/buttonA" />
</android.support.constraint.ConstraintLayout>
0x06 尺寸約束(Dimensions constraints)
設置最小或最大尺寸
可以使用以下屬性:
android:minWidthandroid:minHeightandroid:maxWidthandroid:maxHeight
當 ConstraintLayout寬高設置為 wrap_content時,以上屬性可以起作用。
設置百分比布局
當 ConstraintLayout 子布局的寬或高設置為0dp時,可以對寬或高設置百分比,例如設置一個按鈕的寬是屏幕寬度的30%,那么可以這樣處理:
<android.support.constraint.ConstraintLayout ...>
<!--按鈕width屬性設置為0dp,然后需要指定layout_constraintWidth_default,以及layout_constraintWidth_percent兩個屬性-->
<Button
android:id="@+id/buttonB"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="button B"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.3" />
</android.support.constraint.ConstraintLayout>
設置寬度百分比布局:
layout_width或者layout_height設置為0dp- 設置
layout_constraintWidth_default="percent"或者layout_constraintHeight_default="percent" - 通過
layout_constraintWidth_percent或者layout_constraintHeight_percent指定百分比
設置寬高比例
當 layout_width或者 layout_height設置為0dp時,還可以通過 layout_constraintDimensionRatio設置寬高比例。該比例表示 width:height的值。
<Button android:layout_width="wrap_content" android:layout_height="0dp" app:layout_constraintDimensionRatio="1:1" />
當 layout_width與 layout_height都設置為0dp時,通過 app:layout_constraintDimensionRatio 指定寬高的比例。這時控件的寬高將按照該比例相對於父布局的大小設置寬高。
<android.support.constraint.ConstraintLayout ...>
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,16:9"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
h,16:9的含義是 h:w=16:9 也可設置 w,9:16效果是一樣的。


0x07 Chains
在橫軸或或者數軸上的控件相互約束時,可以組成一個鏈式約束。


圖9中,A控件與B控件相互約束,這就是一個簡單的鏈式約束。
鏈頭


Chain Style
可以通過 layout_constraintHorizontal_chainStyle或 layout_constraintVertical_chainStyle設置鏈式控件的樣式。這個屬性有點像 LinearLayout中的 weight 屬性平分布局。
CHAIN_SPREAD- Weighted chain
CHAIN_SPREAD_INSIDECHAIN_PACKED


設置權重
layout_constraintHorizontal_weightlayout_constraintVertical_weight
0x08 引用
https://developer.android.com/reference/android/support/constraint/ConstraintLayout
