ConstraintLayout详解

来源:互联网 发布:软件定制化开发 编辑:程序博客网 时间:2024/06/06 05:15

简介

ConstraintLayout是谷歌2016年的I/O大会上推出的新控件,Constraint翻译过来就是“约束”的意思,这个控件跟RelativeLayout类似,其子控件通过互相约束来确定位置、大小,但是比RelativeLayout的功能强大很多。使用这个控件作为根布局,可以实现很复杂的布局情况,以前需要嵌套多层才能实现的布局,现在可能一层就够了。

谷歌的演示侧重引导开发者通过鼠标拖控件的方式来写布局,ConstraintLayout也是比较好的支持了鼠标拖动布局,也有不少相关博客主要以拖动讲解为主。但是还是有一些属性无法通过鼠标拖动来完成,比如设置visible、尺寸单位(dp、px)等,所以我想,与其学习“可视化操作布局+xml代码布局”,还不如直接学习“xml代码布局”。

要使用这个控件首先要在gralde中导入,如下:

dependencies {    compile 'com.android.support.constraint:constraint-layout:1.0.2'}

其次,在layout布局文件中要引入自定义属性的命名空间:xmlns:app=”http://schemas.android.com/apk/res-auto”,这样下面的控件才能使用其中的自定义属性:

<?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="wrap_content">    <Button        android:id="@+id/btn1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintLeft_toLeftOf="parent"/></android.support.constraint.ConstraintLayout>

这篇博客分为四部分来讲解ConstraintLayout:
1、第一部分讲解ConstraintLayout中的子控件是如何确定位置的;
2、第二部分讲解子控件是如何确定自身尺寸的;
3、第三部分讲解chains链条特性,非常实用;
4、第四部分讲解一些其它属性;

控件位置

一、基本控制

主要有8个属性来设置控件的位置,跟RelativeLayout差不多:

// 左边向parent父控件的左边靠拢(注意,这里用的是“靠拢”,而不是“对齐”,后面就能体会到了)app:layout_constraintLeft_toLeftOf="parent"// 左边向btn2的右边靠拢。也就是再btn2的右边,相当于RelativeLayout的toRightOfapp:layout_constraintLeft_toRightOf="@+id/btn2"// 下面的6个属性就不一一注释了,参照上面两个,一眼就能看懂app:layout_constraintTop_toBottomOf=""app:layout_constraintTop_toTopOf=""app:layout_constraintRight_toLeftOf=""app:layout_constraintRight_toRightOf=""app:layout_constraintBottom_toBottomOf=""app:layout_constraintBottom_toTopOf=""

在一个水平上设置一个约束是很清楚的,就跟RelativeLayout的toRightOf等属性效果一样,但是如果一个水平上设置两个约束呢?比如下面:

<Button    android:id="@+id/btn1"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    app:layout_constraintRight_toRightOf="parent"    app:layout_constraintLeft_toLeftOf="parent"/>

这就是为什么前面为什么要用“靠拢”这个词了,也可以理解这个控件为什么叫“约束控件”,这些属性都不是绝对的,只是一种约束,控件的最终位置(其他属性也一样)是通过各种约束条件来决定的,而不是像RelativieLayout的toRightOf那样一锤子买卖。

上面的意思就是左边尽量向parent的左边靠拢,右边尽量向parent的右边靠拢,最终就会取一个中间状态,让控件同时满足这两个约束条件,所以这个button最终是居中的。你可以脑补一下,一个力向左边拉,一个相等的力同时向右边拉,所以你最终在中间了。

二、偏向性控制

ConstraintLayout还有个很好用的属性app:layout_constraintHorizontal_bias=”0.1”,用来设置控件位置的偏向性,直接用代码说明:

<Button    android:id="@+id/btn1"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    app:layout_constraintHorizontal_bias="0.2"    app:layout_constraintRight_toRightOf="parent"    app:layout_constraintLeft_toLeftOf="parent"/>

可以这么理解,btn既要向左边靠拢,有要向右边靠拢,然后就取了折中方案居中了。现在设置了layout_constraintHorizontal_bias约束,所以在满足前面两个约束的前提下,还要继续满足第三个约束。这个约束的意思是,在水平方向上,离左边的距离为0.2份,离右边的距离0.8份,也就是离左边更近一些。通过设置这个值,能轻松控制控件的相对于parent、其它控件的位置。

竖直方向的属性是app:layout_constraintVertical_bias=”0.3”,与上面同理,就不展开了。

尺寸设置

尺寸的设置主要有三种方式:通用的属性设置、约束条件设置、宽高比例设置

一、通用属性设置

1、设置具体值
与其它layout一样,设置android:layout_width=”100dp”就可以了。

2、由内容控制
与其它layout一样,设置android:layout_width=”wrap_content”。

二、约束条件设置

设置android:layout_width=”0dp”,意思就是由约束条件控制。举两个例子就明白了:

// 宽度设置为0dp,约束条件既要向parent左边靠拢,又要向parent右边靠拢,结果就是match_parent了<Button    android:id="@+id/btn1"    android:layout_width="0dp"    android:layout_height="wrap_content"    app:layout_constraintRight_toRightOf="parent"    app:layout_constraintLeft_toLeftOf="parent"/>// 宽度设置为0dp,约束条件既要向btn1的左边靠拢,又要向btn1的右边靠拢,结果就是与btn1宽度一样<Button    android:layout_width="0dp"    android:layout_height="wrap_content"    app:layout_constraintRight_toRightOf="@+id/btn1"    app:layout_constraintLeft_toLeftOf="@+id/btn1"/>

注意:如果只是单纯地设置为0dp,而没有其它约束条件来约束尺寸,最终效果就是wrap_content,可以理解为,在没有其它约束条件时,wrap_content就成了唯一约束条件。

三、宽高比例设置

其实这个也属于“约束条件设置”,只是这里的约束条件变成了宽高比例。

ConstraintLayout有个app:layout_constraintDimensionRatio=”2:1”属性,用于控制宽高比例,前面的数字是宽,后面数字是高。

要使这个属性生效,需要要满足两个条件:
1、宽高属性中其中一个属性由约束条件设置,也就是设置为0dp,并且设置了Right_toRight和Left_toLeft属性;
2、另一个属性不能为0dp(从实际使用效果来看,最好设置为固定值,设置为wrap_content的效果很奇怪);

看下代码示例就理解了:

// 最终的效果就是宽是高的2倍。如果height设置为wrap_content,然后通过设置text属性设置内容,最终效果也确实是宽是高的2倍,但是text的内容会换行。。。效果不尽人意。<Button    android:id="@+id/btn2"    android:layout_width="0dp"    android:layout_height="100dp"    app:layout_constraintDimensionRatio="2:1"    app:layout_constraintLeft_toLeftOf="parent"    app:layout_constraintRight_toRightOf="parent"/>


Chains链条布局

链条就是一系列控件在同一水平上首位相连,形成一个整体。实现链条需要满足两个条件:
1、btn1设置靠拢btn2左边,同时btn2要设置靠拢btn1右边,两个控件都要设置属性;
2、最左边的btn要设置靠拢parent左边,最右边的btn要设置靠拢parent右边;

形成chains链条后,这个chains就是一个整体了,通过对head头(该链条上的第一个控件)设置app:layout_constraintHorizontal_chainStyle=”“属性,能够设置这个链条样式。

下面是官网上显示的各种样式链条的效果图:

这里写图片描述

这5个样式分为三类,一类是直接通过style属性设置(样式1、2、4),一类是通过权重设置(样式3),最后一类是通过bias属性设置(样式5)。

一、style属性设置

通过对head头控件设置app:layout_constraintHorizontal_chainStyle属性,可以显示出上面样式1、2、4的效果:

<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">    <Button        android:id="@+id/btn1"        android:layout_width="wrap_content"        app:layout_constraintHorizontal_chainStyle="spread" // 对应样式1(默认样式)        app:layout_constraintHorizontal_chainStyle="spread_inside" // 对应样式2        app:layout_constraintHorizontal_chainStyle="packed" // 对应样式4        android:layout_height="wrap_content"        app:layout_constraintLeft_toLeftOf="parent" // 最左边的链条靠拢parent左边        app:layout_constraintRight_toLeftOf="@+id/btn2" />// 可以看到,btn1靠拢btn2的左边,btn2靠拢btn1的右边,同样btn2和btn3也是如此    <Button        android:id="@+id/btn2"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintLeft_toRightOf="@+id/btn1"        app:layout_constraintRight_toLeftOf="@+id/btn3" />    <Button        android:id="@+id/btn3"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintRight_toRightOf="parent" //最右边的链条靠拢parent右边        app:layout_constraintLeft_toRightOf="@+id/btn2" /></android.support.constraint.ConstraintLayout>


二、权重链

第3种样式是加权链,在链条样式为spread的情况下,通过设置btn的app:layout_constraintHorizontal_weight=”“属性来控制btn宽度,跟LinearLayout是一样的,也需要把宽度设置为0dp,代码如下:

    <Button        android:id="@+id/btn1"        android:layout_width="wrap_content" // 不需要由weight决定宽        android:layout_height="wrap_content"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toLeftOf="@+id/btn2" />    <Button        android:id="@+id/btn2"        android:layout_width="0dp" // width设置为0,让weight决定宽度        android:layout_height="wrap_content"        app:layout_constraintHorizontal_weight="1" // 占剩下空间的1份        app:layout_constraintLeft_toRightOf="@+id/btn1"        app:layout_constraintRight_toLeftOf="@+id/btn3" />    <Button        android:id="@+id/btn3"        android:layout_width="0dp"        app:layout_constraintHorizontal_weight="1" //也占1份,所以剩下空间要与btn2平分        android:layout_height="wrap_content"        app:layout_constraintLeft_toRightOf="@+id/btn2"        app:layout_constraintRight_toRightOf="parent"/>


三、bias链条

在链条样式是packed的情况下,通过设置head头控件的bias属性,来设置链条的位置(更偏向左或更偏向右)

    <Button        android:id="@+id/btn1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintHorizontal_bias="0.3" // 权重为靠左0.3        app:layout_constraintHorizontal_chainStyle="packed" // 样式为packed        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toLeftOf="@+id/btn2" />    <Button        android:id="@+id/btn2"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintLeft_toRightOf="@+id/btn1"        app:layout_constraintRight_toLeftOf="@+id/btn3" />    <Button        android:id="@+id/btn3"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintLeft_toRightOf="@+id/btn2"        app:layout_constraintRight_toRightOf="parent" />


其它属性

一、app:layout_goneMarginLeft=”50dp”

这个属性的意思是,如果左边的控件是可见的,这个属性不生效;如果左边控件设置为gone,这个属性就会生效,离左边间隔50dp。

这个属性与android:layout_marginLeft=”“属性不冲突,可以同时生效。

二、android.support.constraint.Guideline控件

这是一条基准线,没有内容、不会显示、draw方法都是空实现,它的作用就是辅助我们进行控件定位。

android:orientation=”vertical”属性用来设置基准线的方向,垂直线或水平线;

app:layout_constraintGuide_percent=”0.7”属性或android:layout_margin=”“属性用来设置它的位置,percent=0.7就是离父控件左边/上边70%距离,margin=100dp就是离父控件左边/上边100dp

确定了它的方向和位置,我们就可以通过它来定位,设置其它控件的位置了

<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">    <android.support.constraint.Guideline        android:id="@+id/line"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="vertical" // 设置方向和位置        app:layout_constraintGuide_percent="0.7"/>    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintLeft_toRightOf="@+id/line"/></android.support.constraint.ConstraintLayout>

大致的使用就是这些了,只用这个控件,很多布局都变得方便了,嵌套层级减少不是一点两点,视图加载效率也会高很多。

原创粉丝点击