ConstraintLayout入门

来源:互联网 发布:春风沉醉的夜晚知乎 编辑:程序博客网 时间:2024/05/29 17:26

题外话

    AS2.3之后,Android默认的Layout根布局从LinearLayout换成了ConstraintLayout,这东西听说用起来蛮不错的,本着对LinearLayout布局精通的理解(此处微笑脸),很长一段时间都一上来就把ConstraintLayout直接替换成LinearLayout和RelativeLayout,但是换多了,人又变懒了,又不想改XML模版,索性把这个东西学习一下,以防不时之需。话说前有郭霖大神已经介绍了对ConstraintLayout的可视化操作,我没那耐心和习惯,搞多了XML的人,不太想用那个啥可视化,个人感觉就是low,而且命名还不是自己的习惯的,所以还是撸XML源码吧.


开始

导入

    哥哥您先看一下您的AS support Respository中是否安装了ConstraintLayout的支持,不然会有各种bug出现,如下图:

这里写图片描述

然后gradle添加:

    compile 'com.android.support.constraint:constraint-layout:1.0.2'

开始画

有这样一个需求,TextViewA在center处,TextViewB在TextView的右上方,分别使用ConstraintLayout与RelativeLayout写XML,如下图:

这里写图片描述      这里写图片描述
样式肯定是一样的,那么就是说二者之间存在某种对应关系,是的,基本上我们可以认为ContraintLayout就是个加强版的RelativeLayout,那么先贴一下二者的XML文件吧:
RelativeLayout版:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout android:id="@+id/id_parent"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:orientation="vertical">    <TextView        android:id="@+id/id_tv1"        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_centerInParent="true"        android:background="#00bcd4"        android:gravity="center"        android:text="A"        android:textColor="#FFF"        android:textSize="30sp"/>    <TextView        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_toRightOf="@id/id_tv1"        android:background="#009688"        android:gravity="center"        android:text="B"        android:textColor="#FFF"        android:textSize="30sp"/></RelativeLayout>

使用ConstraintLayout:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout    android:id="@+id/id_constraint"    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"    tools:ignore="hardcodeText">    <TextView        android:id="@+id/id_tv1"        android:layout_width="100dp"        android:layout_height="100dp"        android:background="#090898"        android:gravity="center"        android:text="A"        android:textColor="#FFF"        android:textSize="30sp"        app:layout_constraintBottom_toBottomOf="@id/id_constraint"        app:layout_constraintLeft_toLeftOf="@id/id_constraint"        app:layout_constraintRight_toRightOf="@id/id_constraint"        app:layout_constraintTop_toTopOf="@id/id_constraint"/>    <TextView        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_marginLeft="20dp"        android:background="#780979"        android:gravity="center"        android:text="B"        android:textColor="#FFF"        android:textSize="30sp"        app:layout_constraintLeft_toRightOf="@id/id_tv1"/></android.support.constraint.ConstraintLayout>

二者的代码基本上差不多,只是对于某些属性转换一下就可以了,如下图,基本上你可以将RelativeLayout转化成了ConstraintLayout了:

ConstraintLayout属性 RelativeLayout属性 layout_constraintLeft_toLeftOf layout_alignLeft layout_constraintLeft_toRightOf layout_toRightOf layout_constraintRight_toLeftOf layout_toLeftOf layout_constraintRight_toRightOf layout_alignRight layout_constraintTop_toTopOf layout_alignTop layout_constraintTop_toBottomOf layout_below layout_constraintBottom_toBottomOf layout_alignBottom layout_constraintBottom_toTopOf layout_above layout_constraintStart_toEndOf layout_toEndOf(API 17) layout_constraintStart_toStartOf layout_alignStart(API 17) layout_constraintEnd_toStartOf layout_toStartOf(API 17) layout_constraintEnd_toEndOf layout_alignEnd(API 17)

另外,RelativeLayout独有的相对布局属性,ContraintLayout的规则是将父布局(就是ContraintLayout.this)当做一个Id=“parent”的对象来对待,表中可以理解一下:

ConstraintLayout属性 RelativeLayout属性 layout_constraintTop_toTopOf= “parent” layout_alignparentTop= “true” layout_constraintBottom_toBottomOf= “parent” layout_alignparentBottom= “true” layout_constraintLeft_toLeftOf= “parent” layout_alignparentLeft= “true” layout_constraintRight_toRightOf= “parent” layout_alignparentRight= “true” layout_constraintStart_toStartOf= “parent” layout_alignParentStart= “true” layout_constraintEnd_toEnd= “parent” layout_alignParantEnd= “true” layout_constraintLeft_toLeftOf= “parent”
layout_constraintRight_toRightOf= “parent” layout_centerHorizontal=”true” layout_constraintTop_toTopOf = “parent”
layout_constraintBottom_toBottomOf= “parent” layout_centerVertical = “true” layout_constraintLeft_toLeftOf= “parent”
layout_constraintRight_toRightOf=”parent”
layout_constraintTop_toTopOf = “parent”
layout_constraintBottom_toBottomOf= “parent” layout_centerInParent = “true”

一些看上去很重要的属性

固定比例的属性

举个栗子,控件M的左间距和右间距的比例为x : (1-x),就4:6吧,把A控件空白的地方2:3分了,效果图如下:
这里写图片描述

当然有很多中写法,LinearLayout套三个View,TableLayout套三个View,最后还有我们的ConstraintLayout也可以实现,部分代码为:

TableLayout的实现为:

    <TableLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:layout_weight="1">        <TableRow>            <View                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_weight="0.4"/>            <TextView                android:layout_height="100dp"                android:layout_width="100dp"                android:background="@color/colorPrimary"/>            <View                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_weight="0.6"/>        </TableRow>    </TableLayout>

那么ContraintLayout的实现为:

    <android.support.constraint.ConstraintLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:id="@+id/parent"        android:layout_weight="1">        <TextView            android:layout_width="100dp"            app:layout_constraintRight_toRightOf="@id/parent"            app:layout_constraintLeft_toLeftOf="@id/parent"            android:background="#298498"            app:layout_constraintHorizontal_bias="0.4"            android:layout_height="100dp"/>    </android.support.constraint.ConstraintLayout>

只需要一个属性:app:layout_constraintHorizontal_bias,bias的解释为偏向,很好理解,左右两边间距就是偏向引起的,偏得越多了,数据越大,那么左边的间距就越大了。同样还有app:layout_constraintVertical_bias竖直方向的偏向。

固定比例宽高

以前我们在View的宽度与高度未指定具体的数值的时候,要View或者ViewGroup按照比例动态调整宽高比,实现起来步骤一般比较麻烦:等到View/ViewGroup绘制出来之后,先难道其LayoutParams,获取固定边的长度。计算出被动边的长度,最后再将数据set LayoutParams中。但是ContraintLayout提供了layout_constraintDimensionRation属性,使用xml就可以设定。

当然这个也是有条件的,为了使layout_constraintDimensionRation有效,那么目标View的layout_width或者layout_height至少有一个设置为0dp(这个是一个新的概念,来自ConstraintLayout,即MATCH_CONSTRAINT,以前的MATCH_PARENT已经不再被支持了,而且这个值还跟各种layout_constraintXXX一起作用,具体的大家可以自己尝试一下)。

当layout_width或者layout_height只有一方存在具体的值时,layout_constraintDimentionRatio有两种取值:
* 浮点:表示宽度和高度之间的比值 (1,0.5)
* “w : h”形式的比例(1:3,5:2)

分别看一下两种方式:
这里写图片描述

这里写图片描述


当View的layout_width和layout_height都被设置为MATCH_CONSTRANT,也就是0dp的时候,这种情况下,系统会使用满足所有约束条件和比值的最大尺寸。
当需要使用一个维度的尺寸去约束另外一个维度的尺寸,比如我需要用高的尺寸来约束宽时,就需要在比值前面添加W或者H了。
* W,2:3: 以宽度为约束条件,而且width的最大值是父控件的宽度,2:3表明最终view的宽度:高度=2:3。
* H, 2:3: 以高度为约束条件,而且height的最大值是父控件的高度,2:3表明最终view的高度:宽度=2:3。

具体可以看下图:

这里写图片描述

这里写图片描述

使用两种不同的设置方式可以达到相同的效果。

GoneMargin

以前我们在RelativeLayout时代,经常有一些这样的需求,如果某个列表图片不存在,那么就需要把这个ImageView设置为View.GONE,设置之后,与之相关联的layout_toRightOf / layout_toLeftOf就失效了,那么整个XML的排列都混乱了,这当然需要有经验的选手,知道怎么布局,知道怎么排列,才能很好的解决问题。那时候就想,如果这个View被GONE掉了,那么与之关联的View可不可以用一种新的排列方式满足我们要求呢?现在好了,ConstraintLayout给我们提供了一种新的属性:GoneMargin。就像名字一样,布局中存在的两个控件,如果一方Visibility == Gone了,另外一方将会根据layout_goneMargin系列属性重新规划自己的间距。

如下图,TextViewA为50*50dp,TextViewB在TextViewA的右边,且二者之间的距离为100dp,现在设置textViewB的marginLeftGone为150dp,大家看看效果吧。先来张标注图(比较水,大家见谅)

这里写图片描述

现在设置TextView为Gone,看一下TextView的位置变化:

这里写图片描述

没有变化哈,那么这就是GoneMargin的作用了。GoneMargin的全家桶为:

layout_goneMarginStartlayout_goneMarginEndlayout_goneMarginLeftlayout_goneMarginToplayout_goneMarginRightlayout_goneMarginBottom

大伙看到写的,就会明白分别表示的意思,我就不讲了。

Chain

这个玩意说真的,刚开始不是特别好理解,因为比较抽象,而且刚开始的时候感觉比较啰嗦。它是ContraintLayout新加入的控件与控件之间的关系。使用chain组成的多个控件,可以在用一个方向上更简单更容易的完成复杂的布局要求。

具体的代码我就先不放了,因为等到Chain-style的时候会有一大波代码出来,这里只说说需要注意的东西,如果多个控件需要组成chain,也是需要满足条件的。
* 控件之间的布局要相互依赖(我依赖你,你依赖我)
* 最少需要两个控件,相互依赖关系需要保持用一个方向上(都是水平方向[Left_toLeftOf or Right_toLeftOf]或者竖直方向[Top_toBottomOf or Bottom_ToTopOf]的上的依赖)

单单就这个Chain,确实用处不得,基本上属于没什么卵用的感觉,但是你如果你加上chain_style,那么就不一样,先上图,给大家看看这个布局的牛叉之处:

这里写图片描述

上图是各种chain_style的效果图,具体代码可以从这里下载https://github.com/Microhx/studyCodes/blob/master/constraintlayoutdome/src/main/res/layout/activity_multi_chains.xml 。通过设置chain_style,ConstraintLayout可以实现我们使用LinearLayout或者RelativeLayout很难实现的布局。这个的确非常优秀啊。对于具体的代码实现,大家可以参考一下上面的代码,里面都写得比较详细。

这里写图片描述

这个图是官方的图,我也是从某个著名公众号里面盗出来的,对此表示一番感谢。它非常形象的展示了各种chain_style的显示模式,一看就懂,我就不啰嗦了。

对于这个设置,还需要提一下有个东西叫head chain,所谓head,就是chain链最左边的一个或者chain链最顶部的一个。通过设置head chain就可以添加chainStyle属性。本来上面源码里面已经写得很清楚了,本着方便大家的想法,还是把配置列出来,给大家看看:

chain Style 设置方式 Spread Chain chainStyle = “spread” Spread Inside Chain chainStyle = “spread_inside” Packed Chain chainStyle = “packed” Packed Chain with Bias chainStyle = “packed”
layout_constraintHorizontal_bias
layout_constraintVertical weighted Chain chainStyle = “spread”
layout_width = “0dp”
layout_heiht = “0dp”
layout_constraintHorizontal_weight
layout_constraintVertical_height

好了,也扯得差不多了,感谢想扯了都扯完了。比较邋遢啊。

后记

虽说这个ConstraintLayout已经很智能了,但是作为已经写了近两年的android老司机来说,重新使用可视化的编辑器操作XML,而不是手写,多少有些不太习惯。到目前为止,我也没用过几次,个人感觉需要转变这个想法还需要一定的时间,但是对于新手来说还是很有用的。至于绘制的效率,按照Google官方给出的数字,ConstraintLayout要比RelativeLayout高40%左右,为了这个效率,我想今后还有学习的必要,毕竟人是需要进步的嘛。

感谢:
https://mp.weixin.qq.com/s?__biz=MzI1NjEwMTM4OA==&mid=2651232651&idx=1&sn=9ea7beb5c280cd05d192cd3df072a745&chksm=f1d9e4e8c6ae6dfe3aafc910cfd2785249d777a998521047127c5beac2c4657bdd7b6c2a43ac&mpshare=1&scene=1&srcid=0920NjRuoNxvnj45lb9vcw2g#rd

http://blog.csdn.net/zxt0601/article/details/72683379

http://blog.csdn.net/u013706904/article/details/52957946

和自己。

原创粉丝点击