自去年Google I/O 大会发布ConstraintLayout至今,已有一年多的时间,可是并无普及开来,了解过ConstraintLayout布局的人知道,它的性能的确提高了很多。在前不久,Google 开发者博客发布了一篇文章Understanding the performance benefits of ConstraintLayout(中文地址)详细分析ConstraintLayout性能的优点,感兴趣的朋友能够去看看。html
固然本身以前也没有认识到ConstraintLayout布局的性能优点,因此从这篇文章开始由浅入深详细介绍ConstraintLayout的属性及使用,也让本身对ConstraintLayout也有一个更全面的认识,今天的这篇文章主要介绍布局的一些属性,学习地址是Google文档。android
在使用ConstraintLayout以前咱们须要在咱们app下的gradle文件添加ConstraintLayout依赖,截止到目前ConstraintLayout的最新版本是1.0.2.bash
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.2'
}复制代码
#Relative positioning
相对定位的效果和RelativeLayout布局有殊途同归之处,只不过要比RelativeLayout强大。约束能容许咱们指定一个控件相对于另外一个控件的位置,经过一些属性咱们能够对组件进行水平或者垂直排列。例如当咱们使用含有Left, Right, Start 或者End关键词词属性进行定位时便是对组件进行水平方向排列,同理 top, bottom 和 text baseline(文字的基线位置)就是垂直方向排列。具体相对定位的一些属性组合以下app
对于上面这些属性的值有两种,一种就是同层级组件ID,还有就是parent,当值为parent时便是相对于父布局进行定位。ide
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="textView1" />
<TextView
android:id="@+id/textView2"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="textView2"
app:layout_constraintLeft_toRightOf="@+id/textView1" />
</android.support.constraint.ConstraintLayout>复制代码
例如上面的布局,咱们使用app:layout_constraintLeft_toRightOf="@+id/textView1"将textView2的左边和textView1的右边对齐,效果图布局
那么当textView2属性设置为性能
app:layout_constraintTop_toBottomOf="@+id/textView1"
app:layout_constraintLeft_toRightOf="@+id/textView1"复制代码
效果图:
学习
当textView1设置属性 app:layout_constraintRight_toLeftOf="parent"
textView2设置 app:layout_constraintLeft_toLeftOf="parent"时,gradle
效果图:
ui
对于margin值咱们都不陌生,由于咱们常用,有如下几种
须要注意的是此margin只对于设置了约束的地方起做用,以下布局
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
app:layout_constraintLeft_toLeftOf="parent"
android:text="textView1" />
</android.support.constraint.ConstraintLayout>复制代码
咱们只设置了TextView的左边和父布局左边约束,当咱们设置了左边和上边的margin值都为10时,发现只有左边的边距生效,而上边的变化没有发生做用,这也就验证了边距只对有约束行为的地方起做用。
除了咱们经常使用的margin设置属性外,ConstraintLayout 还提供了一些特有的margin设置。先看下面布局
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="textView1"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="textView2"
app:layout_constraintLeft_toRightOf="@+id/textView1" />
</android.support.constraint.ConstraintLayout>复制代码
上面textview2在textview1的右边,那么当咱们因为某种需求将textview1设置了 View.GONE隐藏该控件,那么此时textview2将跑到位置将显示在左上角,若是咱们在隐藏textview时而保持textview2位置不变。在以前的应用中能稍微比较麻烦一点,可是ConstraintLayout 给咱们提供了layout_goneMargin**类的属性,该属性是表示约束隐藏时的margin值。例如上面的textView2咱们增长app:layout_goneMarginLeft="100dp"属性就能够保持当约束textView1隐藏时而保持textview2位置不变。
须要注意的一点是若是某个约束设置了View.GONE,至关于这个组件宽和高为0,约束布局中至关于一个点,其余设置的约束依然有效。
<TextView
android:id="@+id/textView1"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="textView1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />复制代码
若是约束布局中咱们添加textview并设左边和父布局左边,右边和父布局右边对齐,并设置宽度100dp,那么此时效果是怎样的呢。咱们发现textview居中显示了,这就是约束布局的居中定位。
其实咱们能够理解为父布局对textview左边和右边都有一个拉力,因为默认这个力大小相同就到显示到中间位置。
在上面因为两个相反的约束,而使组件居中,在协同布局中还提供了bias,经过属性layout_constraintHorizontal_bias或者layout_constraintVertical_bias设置组件偏向水平或者垂直的某一测,,默认状况下该值是0.5(50%).例如咱们设置textview属性
app:layout_constraintHorizontal_bias="0.3"复制代码
此时组件偏向左边
当咱们的协调布局的子组件设置wrap_content时,咱们能够经过android:minWidth或者android:minHeight 属性设置最小宽度或者高度的约束。minWidth/minHeight只有宽度或者高度为wrap_content才有做用。
对于android:layout_height /android:layout_width属性,它的值只有三种状况
须要注意的是在约束布局中MATCH_PARENT 属性值不在支持,例如在上面的TextView咱们设置layout_width分别是100dp,0dp,0dp(marginLeft :20dp)大体效果如图a,b,c
比例约束能够约束咱们控件的宽高比,例以下面示例
<TextView
android:id="@+id/textView1"
android:layout_width="100dp"
android:layout_height="0dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="textView1"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />复制代码
设置宽度为100dp,高度为0dp,此时设置了宽高比是2:1,则宽度会自动约束调整为50dp。
若是咱们将上面的宽和高度调换,宽为0dp,高100dp,此时最终宽度为200,高度100(宽:高=2:1)
在上面介绍的的宽高比约束是单维度的,那么若是咱们的宽和高都有约束,都设置为0dp,在这种状况下,系统会使用知足全部约束条件和比率的最大尺寸。固然咱们也能够在比例值前面加 W 或者 H 来分别约束宽度或者高度,如H,2:1。
链是一种特殊的约束它能让多个该链链接的 多个Views 平分剩余空间位置
以下咱们建立一个水平链
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/A"
android:layout_width="100dp"
android:layout_height="30dp"
android:background="@color/btnnormal"
android:gravity="center"
android:text="A"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/B" />
<TextView
android:id="@+id/B"
android:layout_width="100dp"
android:layout_height="30dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="B"
app:layout_constraintLeft_toRightOf="@+id/A"
app:layout_constraintRight_toLeftOf="@+id/C" />
<TextView
android:id="@+id/C"
android:layout_width="100dp"
android:layout_height="30dp"
android:background="@color/btnnormal"
android:gravity="center"
android:text="C"
app:layout_constraintLeft_toRightOf="@+id/B"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>复制代码
上面代码的效果图以下,A和C相对于父组件的左边和右边有一个约束,A和B,B和C之间两两相互约束,咱们还须要知道的是对咱们称链的第一个元素组件为链头。以下图A就是该链的链头
对于链头咱们能够经过属性layout_constraintHorizontal_chainStyle(layout_constraintVertical_chainStyle)设置,该属性有三个值,spread ,spread_inside ,packed
app:layout_constraintHorizontal_weight="1"复制代码
给B设置属性
app:layout_constraintHorizontal_weight="2"复制代码
那么此时A,B,C的宽度为1:2:1比例占满父组件宽度。设置权重时链样式不能设置为packed (设置后宽度会收缩为0)
Guideline用于辅助咱们对View进行定位,以及设置约束,它不会再真正的显示,只是起到辅助做用,经常使用属性以下
layout_constraintGuide_percent
该值是0.0到1.0之间,用来设置辅助线在父布局的位置,例如设置0.5,就至关于在父视图宽度的中间50%。
<android.support.constraint.Guideline
android:id="@+id/guideline_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<android.support.constraint.Guideline
android:id="@+id/guideline_v"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<TextView
android:id="@+id/tvguide"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@color/red"
android:gravity="center"
android:text="Guide"
app:layout_constraintBottom_toTopOf="@+id/guideline_h"
app:layout_constraintLeft_toLeftOf="@+id/guideline_v" />复制代码
在上面咱们在约束布局中建立两个辅助线,分别是垂直和水平的辅助线,并将textView的下面和水平辅助线的上面对齐,将TextView的左边和垂直辅助线左边对齐。这样咱们可使用辅助线任意控制View的约束位置。