約束佈局ConstraintLayout的使用(二)
ConstraintLayout可用的約束 (constraint-layout:1.0.2)
- 相對定位
- 邊距(Margins)
- 中心定位
- 可見性行為(View.GONE)
- 鏈(Chains)
- 虛擬助手物件(Guideline)
相對定位
相對定位是ConstraintLayout建立佈局的基本組成部分之一。這些約束允許你指定控制元件相對於另一個位置。
例如,按鈕B要位於按鈕A的右邊
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ButtonA"/>
<Button
android:id="@+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ButtonB"
app:layout_constraintLeft_toRightOf="@id/buttonA"/>
可用的約束屬性:
- 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)
邊距
與RelativeLayout一樣。屬性列表
- android:layout_marginStart
- android:layout_marginEnd
- android:layout_marginLeft
- android:layout_marginTop
- android:layout_marginRight
android:layout_marginBottom
與RelativeLayout不一樣的是,當約束目標visibility屬性設為GONE時,你還可以通過下面的屬性設定邊距:
layout_goneMarginStart
- layout_goneMarginEnd
- layout_goneMarginLeft
- layout_goneMarginTop
- layout_goneMarginRight
- layout_goneMarginBottom
如下面的例子:
<android.support.constraint.ConstraintLayout ...>
<Button
android:id="@+id/buttonA" ...
android:visibility="gone"/>
<Button
android:id="@+id/buttonB" ...
app:layout_goneMarginStart="20dp"
app:layout_constraintLeft_toRightOf="@id/buttonA"/>
</android.support.constraint.ConstraintLayout>
當buttonA 設成gone時,buttonA消失,buttonB距左邊20dp。注意,該屬性只在約束目標設成GONE時生效,設成visible 和 invisible 時該屬性不起作用。
中心定位和偏移
怎麼使控制元件居中呢?可以這樣
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ButtonA"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
layout_constraintLeft_toLeftOf 和 layout_constraintRight_toRightOf 同時起作用,約束像相反的力左右拉動控制元件,使得部件將最終被居中在父容器。這同樣適用於垂直約束。
這種情況下,預設使控制元件居中。但你可以使用下面的屬性使控制元件的位置發生偏移。
- layout_constraintHorizontal_bias
- layout_constraintVertical_bias
例如,下面的設定會使控制元件往左偏移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>
尺寸限制
當 ConstraintLayout 的大小被設定成 WRAP_CONTENT 時,可以使用
- android:minWidth (最小寬度)
- android:minHeight (最小高度)
來進行限制
容器內的控制元件 android:layout_width 和 android:layout_height 有3種情況:
- 使用具體的尺寸
- 使用WRAP_CONTENT
- 使用0dp,這是相當於“ MATCH_CONSTRAINT”
注意!ConstraintLayout內的控制元件儘量不要使用match_parent!
前兩種與其他的佈局類似,最後一種是通過其他的約束條件來確定控制元件的大小。
下面的程式碼使buttonA左邊距父容器50dp,右邊鋪滿剩下的空間。
<android.support.constraint.ConstraintLayout ...>
<Button
android:id="@+id/buttonA"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="ButtonA"
android:layout_marginStart="50dp"
android:layout_marginLeft="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
當容器內的控制元件的長或者寬設為0dp時,可以通過 layout_constraintDimentionRatio 設定此控制元件的長寬比。
例如:
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="測試文字排列"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintDimensionRatio="16:9"/>
效果如下:
按鈕的 寬度:高度 = 16:9 。(也可以用浮點值,表示寬度和高度之間的比率)
當寬和高都設為0dp時,系統將設定最大尺寸滿足所有約束並保持設定的長寬比。上面的例子將android:layout_width改為0dp後效果如下:
也可以通過預先新增W或“H”來分別限制寬度或高度。上面的效果圖程式碼如下:
<Button
android:id="@+id/buttonA"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="測試文字排列"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintDimensionRatio="h,16:9"/>
app:layout_constraintDimensionRatio=”h,16:9” 意思是通過16:9的比例設定button的高度。
感覺這個地方的w和h的設定有點難以理解,事實上,”w”或者”h”完全可以不用設定,佈局可以自動推斷。例如,上面的程式碼約束了寬度,使寬度鋪滿容器,而高度並沒有約束,那麼高度就會根據比例自動調整。
Chains
Chains 為同一方向上(水平或垂直)相互連線(或者說約束)的控制元件提供統一的管理。
Chains 的屬性由這條chain上第一個控制元件所控制,該控制元件稱為chain head。
上圖中控制元件A左邊與父容器接觸,右邊與控制元件B依賴;控制元件B左邊依賴於控制元件A,右邊依賴於控制元件B;控制元件C左邊依賴於控制元件B,右邊依賴於父容器。且該chain為水平方向。
用程式碼表示如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="buttonA"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintRight_toLeftOf="@id/buttonB"
app:layout_constraintLeft_toLeftOf="parent"/>
<Button
android:id="@+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="buttonB"
app:layout_constraintLeft_toRightOf="@+id/buttonA"
app:layout_constraintRight_toLeftOf="@id/buttonC"/>
<Button
android:id="@+id/buttonC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="buttonC"
app:layout_constraintLeft_toRightOf="@+id/buttonB"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
效果圖:
由於ButtonA 為chain head。所以layout_constraintHorizontal_chainStyle 由ButtonA設定。該屬性表示水平方向的chain。還有另一個屬性layout_constraintVertical_chainStyle表示垂直方向。
該屬性有三種值:
- spread 預設值。均勻分佈(控制元件寬為wrap_content或確定值)
- spread_inside 與spread型別,只是chain兩端的控制元件不佔父容器的空間,多餘的空間由chain裡的控制元件平分。
spread_inside chain 上的所有控制元件居中緊挨在一起
效果圖如下:
當設定spread時,可以分別為每個子控制元件設定權重,對應的屬性為layout_constraintHorizontal_weight和layout_constraintVertical_weight,與LinearLayout的weight類似,需要注意的是,此時子控制元件的layout_width需要設成0dp。
當設定packed時,可以設定chain在水平或垂直方向上的偏移量,對應的屬性為layout_constraintHorizontal_bias和layout_constraintVertical_bias,取值在0到1之間。
Guideline
ConstraintLayout還可以通過建立物件guideline來輔助佈局。
Guideline有水平和垂直兩張情況:
- 水平(horizontal)的Guideline高度為0,寬度是ConstraintLayout的寬度
- 垂直(vertical)的Guideline寬度為0,高度是ConstraintLayout的高度
Guideline建立方式:
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline"
app:layout_constraintGuide_begin="52dp"
android:orientation="vertical" />
Guideline 有三種屬性:
- layout_constraintGuide_begin 距離左側或頂部的距離
- layout_constraintGuide_end 距離右側或底部的距離
- layout_constraintGuide_percent float型別。距離left或top的比例。
示例:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline"
app:layout_constraintGuide_begin="52dp"
android:orientation="vertical" />
<Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="buttonA"
app:layout_constraintLeft_toRightOf="@+id/guideline" />
</android.support.constraint.ConstraintLayout>