1. 程式人生 > >約束佈局ConstraintLayout的使用(二)

約束佈局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時生效,設成visibleinvisible 時該屬性不起作用。

中心定位和偏移

怎麼使控制元件居中呢?可以這樣

<?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_toLeftOflayout_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
    spread_inside
    packed

當設定spread時,可以分別為每個子控制元件設定權重,對應的屬性為layout_constraintHorizontal_weightlayout_constraintVertical_weight,與LinearLayout的weight類似,需要注意的是,此時子控制元件的layout_width需要設成0dp

當設定packed時,可以設定chain在水平或垂直方向上的偏移量,對應的屬性為layout_constraintHorizontal_biaslayout_constraintVertical_bias,取值在01之間。

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>