ConstraintLayout 是 Android Studio 2.2 中主要的新增功能之一,也是Google在去年的I/O大会上重点宣传的一个功能。ConstraintLayout 非常适合使用可视化的方式来编写界面,但并不太适合使用 XML 的方式来进行编写。另外,ConstraintLayout还有一个优点,它可以有效地解决布局嵌套过多的问题,它有点类似于 RelativeLayout,但远 比RelativeLayout 要更强大。

1、常用相对位置约束

<!-- 各个边的相对关系 -->
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
<!-- RTL Layout兼容(可以不考虑) -->
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

简单示例:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_constraintBaseline_toBaselineOf="@+id/TextView1"
        android:background="@color/colorPrimary"
        android:text="TextView2"/>

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/TextView1"
        android:background="@color/colorPrimaryDark"
        android:text="TextView3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_控件

        注意:约束布局中必须要约束控件位置,即左和右,上和下要至少有一侧进行约束。

2、控件居中(同时约束左和右,上和下)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_android_02

3、角度定位

<!-- 相对控件 -->
app:layout_constraintCircle="@+id/textView"
<!-- 角度 -->
app:layout_constraintCircleAngle="120"
<!-- 距离 -->
app:layout_constraintCircleRadius="150dp"
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintCircle="@+id/TextView1"
        app:layout_constraintCircleAngle="120"
        app:layout_constraintCircleRadius="150dp"
        android:background="@color/colorPrimary"
        android:text="TextView2"/>

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_xml_03

 4、边距

android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

很熟悉,这里不介绍了

goneMargin:用于约束的控件可见性被设置为gone时候使用的margin值

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_goneMarginLeft="10dp"
        android:background="@color/colorPrimary"
        android:text="TextView2"/>

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:正常情况和隐藏TextView1

android 约束布局 负数 android约束布局例子_android 约束布局 负数_04

 

android 约束布局 负数 android约束布局例子_控件_05

5、偏移

        实现控件居中偏移其实利用边距就能实现,但ConstraintLayout还提供了比例偏移的属性:

<!-- 水平偏移 -->
layout_constraintHorizontal_bias
<!-- 垂直偏移 -->
layout_constraintVertical_bias
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        android:background="@color/colorAccent"
        android:text="TextView1" />

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_xml_06

 6、尺寸约束

(1)指定尺寸xxdp

(2)wrap_content:控件自己计算大小,此时可以使用下面属性控制最大最小宽高

<!-- 最小的宽度 -->
android:minWidth 
<!-- 最小的高度 -->
android:minHeight 
<!-- 最大的宽度 -->
android:maxWidth 
<!-- 最大的高度 -->
android:maxHeight

(3)使用 0dp (MATCH_CONSTRAINT)

        官方不推荐在ConstraintLayout中使用match_parent,可以设置 0dp 配合约束代替match_parent

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_android_07

(4)宽高比

        当宽或高至少有一个尺寸被设置为0dp时,可以通过属性layout_constraintDimensionRatio设置宽高比

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintDimensionRatio="1:1"
        android:background="@color/colorAccent"
        android:text="TextView1" />

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_android_08

7、约束链

        第一个控件为链头可以使用layout_constraintHorizontal_chainStyle设置约束链模式:

CHAIN_SPREAD —— 展开元素 (默认);
CHAIN_SPREAD_INSIDE —— 展开元素,但链的两端贴近parent;
CHAIN_PACKED —— 链的元素将被打包在一起。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/TextView2"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_constraintRight_toLeftOf="@+id/TextView3"
        android:background="@color/colorPrimary"
        android:text="TextView2"/>

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/TextView2"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorPrimaryDark"
        android:text="TextView3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

运行效果(三种模式):

android 约束布局 负数 android约束布局例子_xml_09

         同时,还可以使用layout_constraintHorizontal_weight设置权重

8、屏障Barrier

        例如左侧多个控件长度不固定,右侧控件需要在较长控件的右侧

<!-- 位置:bottom、left、right、top -->
app:barrierDirection
<!-- 引用的控件,多个用“,”隔开 -->
app:constraint_referenced_ids
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/TextView1"
        app:layout_constraintLeft_toLeftOf="parent"
        android:background="@color/colorPrimary"
        android:text="TextTextView2"/>

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="TextView1,TextView2" />

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintLeft_toRightOf="@+id/barrier"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="@+id/TextView2"
        android:background="@color/colorPrimaryDark"
        android:text="TextView3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_android_10

9、Group

        Group可以把多个控件归为一组,方便隐藏或显示一组控件。例如有TextView1、TextView2、TextView3,用Group将TextView1、TextView3归为一组隐藏。

<androidx.constraintlayout.widget.Group
    android:id="@+id/group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone"
    app:constraint_referenced_ids="TextView1,TextView3" />

10、Placeholder

        Placeholder是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.Placeholder
        android:id="@+id/placeholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:content="@+id/TextView1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/colorAccent"
        android:text="TextView1" />
</androidx.constraintlayout.widget.ConstraintLayout>

        上面代码中TextView1本来是应该在布局的右侧顶部,然后使用占位符后,控件最后显示在左侧顶部。

11、Guideline

        Guildline像辅助线一样,在预览的时候帮助你完成布局

<!-- 辅助线方向 垂直vertical,水平horizontal -->
android:orientation
<!-- 开始位置 -->
layout_constraintGuide_begin 
<!-- 结束位置 -->
layout_constraintGuide_end 
<!-- 距离顶部的百分比(orientation = horizontal时则为距离左边) -->
layout_constraintGuide_percent
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="200dp" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="@+id/guideline1"
        android:background="@color/colorAccent"
        android:text="TextView1" />
</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

android 约束布局 负数 android约束布局例子_android_11