新布局ConstraintLayout


引言

ConstraintLayout是Google在2016的Goodle I/O大會(huì)時(shí)提出的,目前的穩(wěn)定版本是1.0.2,它可以降低布局的嵌套層級(jí),提升頁面渲染。

參考文章:

1.幾種屬性介紹

1.2 相對(duì)位置

  • layout_constraintLeft_toLeftOf
    相對(duì)于依賴控件的左邊對(duì)當(dāng)前控件的左邊進(jìn)行約束設(shè)置
  • layout_constraintLeft_toRightOf
    相對(duì)于依賴控件的左邊對(duì)當(dāng)前控件的右邊進(jìn)行約束設(shè)置
  • layout_constraintRight_toLeftOf
    相對(duì)于依賴控件的右邊對(duì)當(dāng)前控件的左邊進(jìn)行約束設(shè)置
  • layout_constraintRight_toRightOf
    相對(duì)于依賴控件的右邊對(duì)當(dāng)前控件的右邊進(jìn)行約束設(shè)置
  • layout_constraintTop_toTopOf
    相對(duì)于依賴控件的頂部對(duì)當(dāng)前控件的頂部進(jìn)行約束設(shè)置
  • layout_constraintTop_toBottomOf
    相對(duì)于依賴控件的底部對(duì)當(dāng)前控件的頂部進(jìn)行約束設(shè)置
  • layout_constraintBottom_toTopOf
    相對(duì)于依賴控件的頂部部對(duì)當(dāng)前控件的底部進(jìn)行約束設(shè)置
  • layout_constraintBottom_toBottomOf
    相對(duì)于依賴控件的底部部對(duì)當(dāng)前控件的底部進(jìn)行約束設(shè)置
  • layout_constraintBaseline_toBaselineOf
    設(shè)置兩個(gè)空間之間的 文字相對(duì)于baseline對(duì)齊
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

效果圖:


布局文件

<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_relative_position"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_A"
        android:text="A"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        style="@style/Constraint_style"/>
    <Button
        style="@style/Constraint_style"
        android:text="在A上方,與A居中對(duì)齊"
        app:layout_constraintLeft_toLeftOf="@id/btn_A"
        app:layout_constraintRight_toRightOf="@id/btn_A"
        android:layout_marginBottom="40dp"
        app:layout_constraintBottom_toTopOf="@id/btn_A"/>
    <Button
        style="@style/Constraint_style"
        android:text="平居中對(duì)齊"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_marginLeft="10dp"
        app:layout_constraintLeft_toRightOf="@id/btn_A"
        app:layout_constraintTop_toTopOf="@id/btn_A"
        app:layout_constraintBottom_toBottomOf="@id/btn_A"/>
    <Button
        style="@style/Constraint_style"
        android:text="在A下方,與A左對(duì)齊"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="@id/btn_A"
        app:layout_constraintTop_toBottomOf="@id/btn_A"
        android:layout_marginTop="100dp"/>
    <Button
        style="@style/Constraint_style"
        android:text="在A下方,與A右對(duì)齊"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintRight_toRightOf="@id/btn_A"
        app:layout_constraintTop_toBottomOf="@id/btn_A"
        android:layout_marginTop="25dp"/>
    <Button
        style="@style/Constraint_style"
        android:text="BASELINE對(duì)齊"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:gravity="bottom"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="10dp"
        app:layout_constraintBaseline_toBaselineOf="@id/btn_A"/>


</android.support.constraint.ConstraintLayout>

1.3 邊距

在ConstrainLayout中,控件除了可以設(shè)置普通的邊距屬性,還可以設(shè)置當(dāng)空間依賴的控件GONE之后的邊距屬性。下面是依賴控件GONE之后的邊距屬性:

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

需求:B控件依賴A,A距離父容器左邊20dp,B在A右邊,距離A為20dp。需求當(dāng)A設(shè)置為GONE之后,B距離父容器左邊60dp。

A在gone之前的效果圖:


<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_margin"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        style="@style/Constraint_style"
        android:id="@+id/btn_a"
        android:text="A"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="100dp"
        />

    <Button
        style="@style/Constraint_style"
        android:text="B"
        android:textAllCaps="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@id/btn_a"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="20dp"
        app:layout_goneMarginLeft="60dp"
        android:layout_marginTop="100dp"
        />

</android.support.constraint.ConstraintLayout>

A在gone之后的效果圖:


1.3 偏移

控件設(shè)置居中(包括水平居中、垂直居中、水平垂直居中)屬性之后,通過偏移屬性可以設(shè)置染空間更偏向于依賴控件的某一方,偏移值設(shè)置為0-1之間的值。

  • layout_constraintHorizontal_bias
    水平偏移
  • layout_constraintVertical_bias
    垂直偏移

效果圖:


布局文件:

<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_margin"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        style="@style/Constraint_style"
        android:id="@+id/btn_a"
        android:text="水平偏移30%"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        />

    <Button
        style="@style/Constraint_style"
        android:text="垂直偏移30%"
        android:textAllCaps="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.3"
        />
    <Button
        style="@style/Constraint_style"
        android:text="水平居中偏移70%"
        android:textAllCaps="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.7"
        app:layout_constraintVertical_bias="0.7"
        />


</android.support.constraint.ConstraintLayout>

1.4可見性

約束布局的可見性屬性:

  • 當(dāng)控件設(shè)為GONE時(shí),被認(rèn)為尺寸為0,可以理解為布局上的一個(gè)點(diǎn);
  • 當(dāng)GONE的控件對(duì)其他控件有約束,則約束保留并生效,但所有的邊距會(huì)清0.

1.5 尺寸

  • 設(shè)置固定尺寸
  • 使用wrap_content,根據(jù)內(nèi)容計(jì)算合適大小
  • match_parent:填滿父布局,此時(shí)設(shè)置的約束都不生效了。
  • 設(shè)置0dp,相當(dāng)于MATCH_CONSTRAINT屬性,基于約束最終確定大小。

MATH_CONSTRAINT

  • layout_constraintWidth_min和layout_constraintHeight_min:設(shè)置最小值
  • layout_constraintWidth_max和layout_constraintHeight_max:設(shè)置最大值
  • layout_constraintWidth_percent和layout_constraintHeight_percent:設(shè)置控件相對(duì)于父容器的百分比大小。使用之前需要先設(shè)置為百分比模式,然后設(shè)置寬高值為0-1之間。
    設(shè)置為百分比模式的屬性:(ConstraintLayout在1.1.x以上才可以用)
app:layout_constraintWidth_default="percent" 
app:layout_constraintHeight_default="percent" 

下面是具體示例:


布局文件:

<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_dimen"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_1"
        android:text="minWidth設(shè)置為200dp"
        android:textAllCaps="false"
        style="@style/Constraint_style"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:minWidth="200dp"
        />

    <Button
        android:id="@+id/btn_2"
        android:text="設(shè)置為MATCH_CONSTRAINT"
        style="@style/Constraint_style"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        app:layout_constraintTop_toBottomOf="@id/btn_1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

    <Button
        android:id="@+id/btn_3"
        android:textAllCaps="false"
        android:text="layout_constrainedWidth開啟"
        style="@style/Constraint_style"
        android:layout_marginTop="10dp"

        app:layout_constraintTop_toBottomOf="@id/btn_2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constrainedWidth="true"
        app:layout_constraintWidth_min="300dp"
        />
    <Button
        android:id="@+id/btn_4"
        android:textAllCaps="false"
        android:text="layout_constrainedWidth關(guān)閉"
        style="@style/Constraint_style"
        android:layout_marginTop="10dp"

        app:layout_constraintTop_toBottomOf="@id/btn_3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintWidth_min="300dp"
        />
    <Button
        android:id="@+id/btn_5"
        android:textAllCaps="false"
        android:text="寬50%高30%布局"
        style="@style/Constraint_style"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        app:layout_constraintTop_toBottomOf="@id/btn_4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintWidth_percent="0.5"
        app:layout_constraintHeight_percent="0.3"
        />
</android.support.constraint.ConstraintLayout>

1.6 比例

控件可以定義自身寬高之間的比例,前提條件是至少有一個(gè)尺寸設(shè)置為0dp,然后通過layout_constraintDimentionRatio屬性設(shè)置寬高比。設(shè)置方式有以下幾種:

  • 直接設(shè)置一個(gè)float值,表示寬高
  • 以“width:height”形式設(shè)置
  • 通過設(shè)置前綴W或H,指定一遍相對(duì)于另一邊的尺寸,如“H,16:9”,高比寬為16:9

如果寬高設(shè)置為odp,也可以用ratio設(shè)置,這種情況下空間會(huì)滿足比例約束的條件下,盡可能填滿父布局。

下面是具體示例:


布局文件:

<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_dimen"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_1"
        android:text="寬高比設(shè)置為2:1"
        style="@style/Constraint_style"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

    <Button
        android:id="@+id/btn_2"
        android:text="寬高都設(shè)置為0dp,高寬比為16:9"
        style="@style/Constraint_style"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="H,16:9"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn_1"
        android:textAllCaps="false"
        />

</android.support.constraint.ConstraintLayout>

1.7 鏈

鏈這個(gè)概念是約束布局新提出的,它提供了在一個(gè)維度(水平或者垂直),管理一組空間的方式。

2. Guideline

用于布局輔助,不在設(shè)備上顯示。有垂直和水平兩個(gè)方向(android:orientation=“vertical/horizontal”)

  • 垂直:寬度為0,高度等于父容器
  • 水平:高度為0,寬度等于父容器

有三種放置Guideline的方式:

  • 給定距離左邊或頂部一個(gè)固定距離(layout_constraintGuide_begin)
  • 給定距離右邊或底部一個(gè)固定距離(layout_constraintGuide_end)
  • 給定寬高一個(gè)百分比距離(layout_constraintGuide_percent)

具體示例:


布局文件:

<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_dimen"
    android:padding="16dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--垂直Guideline-->
    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.5"
        android:orientation="vertical"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        />
    <Button
        android:id="@+id/btn_1"
        android:textAllCaps="false"
        android:text="Guideline左邊"
        style="@style/Constraint_style"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        />


    <Button
        android:id="@+id/btn_2"
        android:textAllCaps="false"
        android:text="Guideline右邊"
        style="@style/Constraint_style"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        />

    <!--水平Guideline-->
    <android.support.constraint.Guideline
        android:id="@+id/h_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintGuide_begin="200dp"
        />
    <Button
        android:id="@+id/btn_3"
        android:textAllCaps="false"
        android:text="Guideline上面"
        style="@style/Constraint_style"
        app:layout_constraintBottom_toBottomOf="@id/h_guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        />
     <Button
        android:id="@+id/btn_4"
        android:text="Guideline下面"
        style="@style/Constraint_style"
        app:layout_constraintTop_toTopOf="@id/h_guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        />

</android.support.constraint.ConstraintLayout>

3. ConstraintSet

通過ConstraintSet,允許在代碼中進(jìn)行約束設(shè)置,進(jìn)行布局變換。(API 19及以上支持transmition動(dòng)畫)
創(chuàng)建ConstraintSet對(duì)象的幾種方式:

  • 手動(dòng)
c = new ConstraintSet(); 
c.connect(....);
  • 通過一個(gè)R.layout.xxx對(duì)象
c.clone(context, R.layout.layout1);
  • 通過一個(gè)ConstraintLayout對(duì)象
c.clone(clayout);

布局變化開啟平滑動(dòng)畫的方式:

TransitionManager.beginDelayedTransition(constraintLayout);

其中參數(shù)constraintLayout表示動(dòng)畫作用的約束布局對(duì)象。
更多關(guān)于ConstraintSet的知識(shí)可以參考這篇文章。

4.實(shí)踐

效果圖:



要求:圖片寬高比16:9,圖片寬度固定110dp。

分析:寬高比16:9,需要比例布局;其他都是一些位置關(guān)系,用約束布局相對(duì)位置的一些約束可以實(shí)現(xiàn)。

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
                                             android:paddingLeft="15dp"
                                             android:paddingTop="12dp">

    <ImageView
        android:id="@+id/iv_course"
        android:layout_width="110dp"
        android:layout_height="0dp"
        android:scaleType="fitXY"
        android:src="@mipmap/head"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_course_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="15dp"
        android:ellipsize="end"
        android:maxLines="2"
        android:textColor="#333333"
        android:textSize="15sp"
        app:layout_constraintLeft_toRightOf="@id/iv_course"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/iv_course"
        android:text="六年級(jí)單元過關(guān)檢測六年級(jí)單元過關(guān)檢測六年級(jí)單元過關(guān)檢測" />


    <TextView
        android:id="@+id/tv_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:layout_marginTop="5dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="#666666"
        android:textSize="12sp"
        app:layout_constraintLeft_toLeftOf="@id/tv_course_name"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_course_name"
        android:text="內(nèi)容內(nèi)容內(nèi)容內(nèi)容內(nèi)容" />

    <TextView
        android:id="@+id/tv_current_price"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:maxLines="1"
        android:textColor="#f6454a"
        android:textSize="15sp"
        app:layout_constraintLeft_toLeftOf="@id/tv_course_name"
        app:layout_constraintTop_toBottomOf="@id/tv_content"
        android:text="¥ 480" />

    <TextView
        android:id="@+id/tv_origin_price"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:maxLines="1"
        android:textColor="#999999"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="@id/tv_current_price"
        app:layout_constraintLeft_toRightOf="@id/tv_current_price"
        android:text="¥ 1480" />

</android.support.constraint.ConstraintLayout>

針對(duì)上面的效果
要求:圖片寬度占整個(gè)布局30%,寬高比16:9。
分析:看到30%,首先考慮的是百分比布局,但是圖片右邊的view較多,每個(gè)都是設(shè)置一邊百分比,實(shí)在是麻煩。因此,可以考慮使用Guideline,設(shè)置Guideline垂直,并距離父容器左邊30%的距離,之后布局通過Guideline設(shè)置約束即可。
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:paddingLeft="15dp"
    android:paddingTop="12dp">

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

    <ImageView
        android:id="@+id/iv_course"
        android:layout_width="110dp"
        android:layout_height="0dp"
        android:scaleType="fitXY"
        android:src="@mipmap/test"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent"
 />
...

要求:在之前基礎(chǔ)上,底部加一根橫線用于分隔,要求線與上面最近的控件距離是15dp。
分析:由于文字內(nèi)容是可變的,當(dāng)文字內(nèi)容多的時(shí)候,線可能距離文字近;若文字不多,線也可能距離圖片近。這個(gè)時(shí)候,基于當(dāng)前最新1.0.2穩(wěn)定版本的約束布局已經(jīng)不能滿足我們實(shí)現(xiàn)一層布局了,還是需要將圖片和文字整體放入一個(gè)布局容器中,然后橫線依賴這個(gè)布局容器設(shè)置約束實(shí)現(xiàn),嵌套好像在所難免了。然而,當(dāng)約束布局1.1.0穩(wěn)定版本發(fā)布時(shí),這問題也可以得到解決。我們先來看看在1.1.0上是怎么實(shí)現(xiàn)的:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:paddingLeft="15dp"
    android:paddingTop="12dp">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:layout_editor_absoluteY="0dp"
        tools:layout_editor_absoluteX="104dp"/>

    ...
    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="iv_course, tv_origin_price"
        tools:layout_editor_absoluteY="79dp"
        tools:layout_editor_absoluteX="0dp"/>

    <View
        android:layout_width="329dp"
        android:layout_height="1dp"
        android:background="#d8d8d8"
        android:layout_marginTop="12dp"
        app:layout_constraintTop_toBottomOf="@+id/barrier"
        />
</android.support.constraint.ConstraintLayout>

具體關(guān)于Barrier的用法我們可以繼續(xù)往下看。

5. ConstraintLayout的性能

  • 相對(duì)于傳統(tǒng)布局,ConstraintLayout的布局層級(jí)減少了
  • 具體一些性能的對(duì)比,如渲染速度和計(jì)算次數(shù)等,可以參考這篇文章,< 了解使用 ConstraintLayout 的性能優(yōu)勢>,通過結(jié)論可知使用了ConstraintLayout,布局計(jì)算次數(shù)降低了,渲染速度也相應(yīng)提升了。

6. 布局編輯器

Android studio 2.2之前的布局編輯器不夠完善,部分約束不能設(shè)置,因此推薦使用版本為2.3或者更高的Android studio。關(guān)于布局編輯器可以參考下面這兩邊文章:

7. ConstraintLayout使用小結(jié)

7.1 margin只能設(shè)置正值或者0,負(fù)值無效

我們之前實(shí)現(xiàn)重疊布局時(shí),或通過設(shè)置負(fù)的margin值實(shí)現(xiàn),但是在約束布局中,負(fù)的margin值不會(huì)生效,只能設(shè)置0或者大于0 的值,小于0也當(dāng)做0處理

7.2 鏈的書寫方式注意

一般布局我們都是遵守先定義,后使用原則,但是約束布局實(shí)現(xiàn)鏈時(shí),這個(gè)原則就遵守不了了,這個(gè)時(shí)候如果還是按照常規(guī)的@id/btn_2的方式指定一來控件(這個(gè)控件在當(dāng)前控件之后聲明),就會(huì)報(bào)Error:(23, 46) No resource found that matches the given name錯(cuò)誤。解決方案其實(shí)很簡單,只需修改指定方式如下:@+id/btn_2即可。

7.3 ConstraintSet動(dòng)畫Api支持等級(jí)

在代碼中設(shè)置控件約束,可以通過ConstraintSet實(shí)現(xiàn)。約束變了之后,布局肯定會(huì)跟著變。TransitionManager.beginDelayedTransition提供了平滑動(dòng)畫變換布局的能力,但是只支持Api 19及以上的版本。

7.4 自定義GuideLine

對(duì)Guideline設(shè)置相對(duì)位置屬性時(shí)不生效的,因此當(dāng)我們想要一個(gè)相對(duì)于某個(gè)View的Guideline時(shí),約束布局時(shí)不能滿足我們的要求的,看Guideline源碼:

public class Guideline extends View {
    public Guideline(Context context) {
        super(context);
        super.setVisibility(8);
    }
    ...    
}

發(fā)現(xiàn)Guideline是一個(gè)不可見的view,那么我們可以布局時(shí)放置一個(gè)不可見的view來作為Guideline的替代品,實(shí)現(xiàn)一些特殊布局要求。如布局重疊:

<?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/btn_a"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:text="B"
        android:textSize="20sp"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#fd368d"
        tools:layout_editor_absoluteY="0dp"/>
    <View
        android:id="@+id/view"
        android:layout_height="0dp"
        android:layout_width="0dp"
        app:layout_constraintBottom_toBottomOf="@id/btn_a"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="40dp"/>
    <Button
        android:text="A"
        android:layout_height="200dp"
        android:layout_width="wrap_content"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:background="@color/colorPrimary"
        app:layout_constraintTop_toBottomOf="@id/view"/>

</android.support.constraint.ConstraintLayout>

效果圖:



這種方式可以彌補(bǔ)margin不能設(shè)置為負(fù)值的不足

7.5 區(qū)分0dp、match_parent和MATCH_CONSTRAINT

  • 0dp等價(jià)于MATCH_CONSTRAINT,對(duì)控件設(shè)置其他尺寸相關(guān)約束會(huì)生效,如app:layout_constraintWidth_min等約束
  • match_parent,填充滿父布局,之后設(shè)置約束屬性無效

7.6 使用布局編輯器多出了一些屬性

layout_optimizationLevel
layout_editor_absoluteX
layout_editor_absoluteY
layout_constraintBaseline_creator
layout_constraintTop_creator
layout_constraintRight_creator
layout_constraintLeft_creator
layout_constraintBottom_creator

這幾個(gè)屬性是 UI 編輯器所使用的,用了輔助拖拽布局的,在實(shí)際使用過程中,可以不用關(guān)心這些屬性。

8. 1.1.0-beta3的新特性

  • Barrier
    Barrier是一個(gè)虛擬的輔助控件,它可以阻止一個(gè)或者多個(gè)控件越過自己,就像一個(gè)屏障一樣,當(dāng)某個(gè)控件要越過自己的時(shí)候,Barrier會(huì)自動(dòng)移動(dòng),避免自己被覆蓋。
  • Group
    Goup幫助你對(duì)一組控件進(jìn)行設(shè)置,最常見的情況就是控制一組控件的visibility,你只需把控件的id添加到group,就能同時(shí)對(duì)立面的所有控件進(jìn)行操作。
  • Circular positioning
    可以相對(duì)另一個(gè)控件,以角度和距離定義當(dāng)前控件的位置,即提供了在圓上定義控件位置的能力,如圖所示:


  • Placeholder
    Placeholder顧名思義,就是用來一個(gè)占位的東西,它可以把自己的內(nèi)容設(shè)置為ConstraintLayout內(nèi)的其他view,因此它用來寫布局的模板,也可以用來動(dòng)態(tài)修改UI的內(nèi)容。
  • 百分比布局
    允許設(shè)置控件占據(jù)可用空間的百分比,大大增加布局靈活度和適配性。

具體文章參考Constraint Layout 1.1.x帶來了哪些新東西?

9. ConstraintLayout的優(yōu)勢

  • 布局高效
  • 輕松對(duì)應(yīng)復(fù)雜布局
  • 嵌套層級(jí)少
  • 適配性好
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容