1. 程式人生 > >ConstraintLayout的基本用法及優點

ConstraintLayout的基本用法及優點

為什麼推薦使用ConstraintLayout

ConstraintLayout(約束佈局)在2016年的Google I/O大會上就推出來了,經歷這兩年的迭代,功能已經非常的成熟了。一次偶然的機會,在專案中嘗試了使用約束佈局,從此被它的功能所深深折服。它能很輕易的將你從使用層層的巢狀去實現複雜的佈局中解放出來。使用ConstraintLayout後基本可以拋棄LinearLayout和RelativeLayout的使用。完全不需要任何巢狀就可以實現複雜的UI,使用起來特別清爽。所以相信我,使用過就會愛上它。

約束佈局的終極奧義!

① 如何才能使用?

因為ConstraintLayout的是在Support包中提供的,所以只需要在我們主Module的build.gradle

中新增如下依賴:

implementation 'com.android.support.constraint:constraint-layout:1.1.3'

然後,我們就可以直接在我們的xml檔案中直接應用了:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:
tools="http://schemas.android.com/tools" android:background="@color/white" xmlns:app="http://schemas.android.com/apk/res-auto"> <!--具體佈局--> </android.support.constraint.ConstraintLayout>

② 可以用來幹什麼?

  • layout_constraintDimensionRatio(控制佈局比例):
    我們經常會遇到某些佈局需要展示特殊的比例(16:9、2:1、4:3等等)。在以前我們可能會自定義一個ViewGroup,動態的去計算比例,比較麻煩。而使用ConstraintLayout後,我們可以直接使用這個屬性,以設定某個View的長寬比例為16:9為例:
<ImageView
    android:layout_width="match_parent"
    android:layout_height="@dimen/dimen_0dp"
    app:layout_constraintDimensionRatio="16:9"/>

在這裡插入圖片描述

  • layout_constraintRight_toRightOf(與RelativeLayout相似的屬性toRightOf等一整套的屬性):
    如果你想使用RelativeLayout中的toLeftOf或者toRightOf等屬性,約束佈局同樣提供了一套類似的屬性。比如:按鈕A在螢幕的左上方;按鈕B在按鈕A的右方;按鈕C在按鈕B的下方並且水平居中;按鈕D在按鈕C的下方並且處於螢幕的右側。
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@color/white"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Button
        android:id="@+id/this_is_a"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="A"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:id="@+id/this_is_b"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="B"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/this_is_a"/>

    <Button
        android:id="@+id/this_is_c"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="C"
        android:layout_marginTop="@dimen/dimen_10dp"
        app:layout_constraintTop_toBottomOf="@+id/this_is_b"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <Button
        android:id="@+id/this_is_d"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="D"
        android:layout_marginTop="@dimen/dimen_10dp"
        app:layout_constraintTop_toBottomOf="@+id/this_is_c"
        app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

相對佈局類似屬性示例圖

  • layout_constraintHorizontal_chainStyle
    對於按鈕A和按鈕B在橫向上,我們通過更改其chainStyle屬性(packed、spread、spread_inside)。
    <Button
        android:id="@+id/this_is_a"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="A"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintRight_toLeftOf="@+id/this_is_b"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:id="@+id/this_is_b"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="B"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/this_is_a"/>

在這裡插入圖片描述

  • Barrier

我們經常會有這樣的需求,我們某一個控制元件必須在某一組控制元件的某一側。如下圖所示button和textView無論位置或者長度怎麼變化,checbox始終在他們的右側。
在這裡插入圖片描述

xml中我們需要使用android.support.constraint.Barrier:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@color/white"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Button
        android:id="@+id/this_is_a"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="AAAAAAAAAAAAAAAAAA"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/this_is_b"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="BBBB"
        app:layout_constraintTop_toBottomOf="@+id/this_is_a"/>

    <android.support.constraint.Barrier
        android:id="@+id/this_is_barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="end"
        app:constraint_referenced_ids="this_is_a,this_is_b"
        />

    <CheckBox
        android:id="@+id/this_is_c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        android:layout_marginTop="@dimen/dimen_10dp"
        app:layout_constraintLeft_toRightOf="@+id/this_is_barrier"/>
</android.support.constraint.ConstraintLayout>
  • Group
    在以前,如果我們需要控制某一組控制元件的隱藏或者顯示,通常會使用一個ViewGroup包裹一下,但是現在有了Group,完全不需要了,還是上面同樣的例子,我們加一個Group:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@color/white"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Button
        android:id="@+id/this_is_a"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="AAAAAAAAAAAAAAAAAA"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/this_is_b"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="BBBB"
        app:layout_constraintTop_toBottomOf="@+id/this_is_a"/>
        
    <android.support.constraint.Group
        android:id="@+id/this_is_group"
        android:visibility="invisible"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="this_is_a,this_is_b"/>

    <android.support.constraint.Barrier
        android:id="@+id/this_is_barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="end"
        app:constraint_referenced_ids="this_is_a,this_is_b"
        />

    <CheckBox
        android:id="@+id/this_is_c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/dimen_20sp"
        android:textColor="@color/black"
        android:text="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        android:layout_marginTop="@dimen/dimen_10dp"
        app:layout_constraintLeft_toRightOf="@+id/this_is_barrier"/>
</android.support.constraint.ConstraintLayout>

通過控制Group的可見性即可控制referenced_ids中申明的控制元件組的可見性了。注意一點,不要把一個控制元件申明在不同的Group中,這樣有可能會導致設定可見性失效哦。

  • Guideline

利用這個控制元件,可以輔助我們佈局UI。在實際執行以後,這條線我們是看不到的:
在這裡插入圖片描述

佈局我們可以這麼寫:

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="16dp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="TextView" />

</android.support.constraint.ConstraintLayout>

有什麼優點

上面介紹了ConstraintLayout的部分功能,強烈推薦你去使用感受一下,在你使用過程中才能真正的體會到爽快。那我們使用約束佈局會有什麼優點呢?
我們使用ConstraintLayout之後,減少了很多的巢狀的層級。這樣View在渲染的時候,減少了很多多餘的measurelayout的開銷。據統計,使用約束佈局替代以前的巢狀結構可以提升40%的速度。如果你巢狀的層次越多,提升的效果越明顯。所以,建議我們現在的開發者強制推行使用ConstraintLayout,無論從開發速度還是頁面的渲染速度都是提升明顯的。

更多Android、Java進階知識微信搜尋公眾號:南京Android部落