ConstraintLayout属性介绍及使用

ConstraintLayout属性介绍及使用


相信大家对ConstraintLayout并不陌生,Android Studio升级2.2之后,默认生成的XML布局已经从原来的RelativeLayout替换为ConstraintLayout,并且goole在去年的I/O大会上重点推出介绍了这个控件,对于ConstraintLayout到目前为止已经推出了很多的使用方法和属性还是比较给力的,并且到目前为止Google还在继续丰富其API和功能,所以这对于开发者而言是一个大的福音!下面我们就来看看它到底高明在哪里!!!

说明:因为文章中会用到大部分的ConstraintLayout的名词,我们在文章中会使用CL缩写来代替,使用RL代替RelativeLayout。

要引入ConstraintLayout的使用,我们需要在gradle文件中添加

implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta3'

Relative positioning(相对位置)

循序渐进,我们从最基本的来,这是我使用ConstraintLayout写的一个布局效果:

在这里插入图片描述

这样的布局是我们平时很常见的效果,下面我们就看看使用ConstraintLayout时如何实现的:

<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="match_parent"
    tools:context="com.example.ljj.constraintlayoutdemo.demolist.RelativePositioningActivity">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:title="相对位置"
        app:titleTextColor="@android:color/white" />

    <TextView
        android:id="@+id/text_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/fab_margin"
        android:layout_marginTop="@dimen/fab_margin"
        android:text="奚梦瑶维密秀摔倒道歉"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar" />

    <ImageView
        android:id="@+id/image"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@drawable/image"
        app:layout_constraintLeft_toLeftOf="@id/text_title"
        app:layout_constraintTop_toBottomOf="@+id/text_title" />

    <TextView
        android:id="@+id/text_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="@dimen/fab_margin"
        android:text="11月20日晚,一众国内外维密天使闪亮登场。但在表演环节中,奚梦瑶不慎出现意外跌倒在台上,意外发生后,奚梦瑶立刻整理了一下头发和身上的装饰,站起身来继续走T台,并且露出专业和自信的笑容,全场观众也为她拍手鼓励。"
        app:layout_constraintLeft_toRightOf="@+id/image"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/image" />


    <TextView
        android:id="@+id/text_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="时间:2小时前"
        app:layout_constraintLeft_toLeftOf="@id/image"
        app:layout_constraintTop_toBottomOf="@+id/image" />
</android.support.constraint.ConstraintLayout>

从上面代码中可以发现,我们可以看到一共四个控件元素,在text_title中有两个属性:

app:layout_constraintLeft_toLeftOf="parent"

不难理解,此属性的意思是text_title元素的左侧和父布局的左侧对齐,这是和父布局设置的相对依赖关系

app:layout_constraintTop_toBottomOf="@+id/toolbar"

此属性的意思是text_title的顶部在toolbar控件的下方,这是text_title设置的和toolbar位置上的依赖关系,如果我们希望控件A在控件B的下面,就可以这么写。

继续往下看text_content中还设置了

app:layout_constraintTop_toTopOf="@+id/image"

此属性的作用是使text_content和image空间顶部对齐,相当于RL中的marginTop。

这些属性的使用并不难理解,和RL中除了写法不同,理解起来都差不多,但是写的过程中,我发现了一些细节:
1、说明,如果直接设置marginLeft是不起作用的,需要和layout_constraintLeft_toLeftOf等对应的属性搭配使用
2、我们将text_content的 android:layout_width=”0dp”设置为0dp,这就跟RL的写法不同了,稍后介绍这个属性,下面先看小CL提供的相对位置依赖的属性:其中大部分在上面的例子中已经涉及到了,也不难理解,大家可以自己试下。

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
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

MATCH_CONSTRAINT

我们在上面留了一个问题,就是

android:layout_width="0dp"

将宽度设置为0dp在CL中意味着什么呢?
现将android:layout_width修改为wrap_content试试,效果如下:

在这里插入图片描述

可以看到text_content的内容已经脱离了之前的依赖,对于解决这种问题,我们就可以使用0dp的设置,那这个0dp又以为只什么呢?官方是这样介绍的:

Using 0dp, which is the equivalent of "MATCH_CONSTRAINT"
Important: MATCH_PARENT is not recommended for widgets contained in a 
ConstraintLayout. Similar behavior can be defined by using MATCH_CONSTRAINT
 with the corresponding left/right or top/bottom constraints being
  set to "parent".

也就是说在CL中MATCH_PARENT已经不存在了,对于这个属性值,我们就介绍到这里,至于为什么要这样改,我也不知道CL是怎么想的

Centering positioning And Bias (居中和偏移量)

上代码:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ....
    ">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        ... />

    <Button
        android:id="@+id/button_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/fab_margin"
        android:text="居中"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/button_bias"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/fab_margin"
        android:text="偏移量"
        app:layout_constraintHorizontal_bias="0.1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_center" />

</android.support.constraint.ConstraintLayout>

对应实现效果:
在这里插入图片描述

先看居中的button_center 元素设置了两个属性:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

设置这两个属性之后说明父布局的左右拉力对button是相等的,所以button居中,使用CL写XML时,左右居中使用上面两个属性,相对应的上下居中使用属性:

app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

再看button_bias的属性中多了一个

app:layout_constraintHorizontal_bias="0.1"

此属性就是设置水平方向的偏移量,0.1表示左右侧距离比为1:9,此属性必须和居中属性一起显示才会起作用,相对应的还有

layout_constraintVertical_bias

Circular positioning(圆形定位)

看到这个功能时我是激动的,瞬间觉得CL提升了一个档次,圆形定位的相关属性是在CL1.1版本新增的功能,个人感觉很好用,然后就路转粉了,哈哈,我先贴出一张图:

在这里插入图片描述

相信大家对这个类型的布局都不陌生,无论是项目中增加新功能,还是IM聊天中有新消息,都会有类似的需求,下面来瞅瞅CL是如何实现的

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ...>

    <ImageView
        android:id="@+id/image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/icon_circle"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/image_point"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/red_point"
        app:layout_constraintCircle="@id/image"
        app:layout_constraintCircleAngle="35"
        app:layout_constraintCircleRadius="40dp" />

</android.support.constraint.ConstraintLayout>

从XML中可以看出image_point也就是上面的原点提示中有三个属性:

app:layout_constraintCircle="@id/image"   //表示以image为原点
app:layout_constraintCircleAngle="35"     //与数值角度为35的方向上布局此控件
app:layout_constraintCircleRadius="40dp"  //半径40

对这三个属性,官方给了一张图非常清楚的表达了这三个参数的含义:

在这里插入图片描述

提示:此属性是CL在1.1版本新增的,如果要使用,请把你的CL升级为1.1

Margins

对于margins,CL也提出了一些属性,如下:

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

但是因为这些属性和RL中的意义和使用方式都相同,所以这里不做过多的介绍,重点介绍下我们之前没有的

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

这几个属性和上面的不同之处在于前面多了一个gone,什么意思呢,上图来说话:

在这里插入图片描述

这是使用CL写的依赖布局:底部文字依赖于图片,在图片的下方,如果我将上面的图隐藏掉,会这样子

在这里插入图片描述

但是怎么办,我的需求是即使将图片隐藏掉,我底部的文字位置不变,这是这个新的属性就可以起作用了,在下面的文字上设置

app:layout_goneMarginTop="100dp"

ok啦,你尽管去GONE,我才不怕:
在这里插入图片描述

注:当text的位置依赖的元素GONE之后,此属性才会起作用

ratio (宽高比)

关于设置ratio的属性如下:

app:layout_constraintDimensionRatio="2:1" 
app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintDimensionRatio="w,2:1"
<TextView
   android:layout_width="0dp"
   android:layout_height="0dp"
   android:background="@color/colorAccent"
   app:layout_constraintDimensionRatio="2:1"
   app:layout_constraintLeft_toLeftOf="parent"
   app:layout_constraintRight_toRightOf="parent"
   />

在XML中,设置了app:layout_constraintDimensionRatio=”2:1”方法,对于这个控件来说,其宽高比为2:1,如图
在这里插入图片描述

我们在设置ratio时,将宽高都设置为match_constraint,就是0dp,并且添加了如下属性才会起作用:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

除此之外,还有两个属性:

app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintDimensionRatio="w,2:1"

可以自己试一下,在水平和竖直方向设置时对应的不同效果。

Chains(链条)

今天很累,写到这里已经语无伦次的赶脚,快刀斩乱麻,直接上图:

在这里插入图片描述

看到官网介绍,将chains相关的属性和使用情况都试了一遍,大致就是这样纸滴,对这些形状分别介绍写法:

1、三个控件等分,类似于项目底部tab实现
在这里插入图片描述

<Button
        android:id="@+id/button1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="乱花"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/button2" />

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="渐欲"
        app:layout_constraintLeft_toRightOf="@id/button1"
        app:layout_constraintRight_toLeftOf="@id/button3" />

    <Button
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="迷人眼"
        app:layout_constraintLeft_toRightOf="@id/button2"
        app:layout_constraintRight_toRightOf="parent" />

为每个元素添加两两相互依赖,来实现等分功能,在这里我们还可以通过

app:layout_constraintHorizontal_weight

来控制每个元素的Item,这里的weight使用和LL中的使用方式一致,如果我将他们的weight设置分别为1,1,2,则效果为:

在这里插入图片描述

注:实现横向等分功能,必须设置宽度为0dp,并且两两互相依赖。

2、效果2,下面两张图是效果实现和官网上对这种效果的chains(链)作用力
在这里插入图片描述

在这里插入图片描述

可以看到A为head,在head元素中设置其chainStyle可以改变对链条之前的相互作用力,来实现不同效果

<Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_top"
        android:text="浅草"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/button5"
        app:layout_constraintTop_toBottomOf="@id/button1" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="才能"
        app:layout_constraintLeft_toRightOf="@id/button4"
        app:layout_constraintRight_toLeftOf="@id/button6"
        app:layout_constraintTop_toTopOf="@id/button4"

        />

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="没马蹄"
        app:layout_constraintLeft_toRightOf="@id/button5"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/button4" />
app:layout_constraintHorizontal_chainStyle="spread"
android:layout_width="wrap_content"

这两个属性组合实现上述效果,注,chainStyle的默认值是spread,如果不设置chainStyle的属性,则默认为spread

3、效果三

实现:

app:layout_constraintHorizontal_chainStyle=“spread_inside”
android:layout_width=“wrap_content”
1
2
4、效果四
在这里插入图片描述

实现:

app:layout_constraintHorizontal_chainStyle="packed"
android:layout_width="wrap_content"

除此之外,效果4还可以和我们上面介绍的Bias(偏移量一起使用),实现偏移效果。

总结:所以app:layout_constraintHorizontal_chainStyle有三个不同的取值,分别是spread、packed、spread_inside,不同的属性值和宽高值设置可以实现不同的效果,如上面介绍,如果还不是很清楚,稍后会附上源码。

guideLine(辅助线)

guideLine也是CL在1.1版本新增的功能,主要用于辅助布局,即类似为辅助线,横向的、纵向的。该布局是不会显示到界面上的。提供了三个属性:

layout_constraintGuide_begin
layout_constraintGuide_end
layout_constraintGuide_percent

先来看一下其实现

<android.support.constraint.ConstraintLayout 
...>
    <!--辅助线1 竖直辅助线,距离左侧100dp-->
    <android.support.constraint.Guideline
        android:id="@+id/guide_line"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp"
        />

    <!--竖直线2 水平辅助线,距离上测150dp-->
    <android.support.constraint.Guideline
        android:id="@+id/guide_line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="150dp" />

    <!--button1位置在两个辅助线的交点位置,通过两个辅助线来控制控件位置-->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button1"
        app:layout_constraintBottom_toBottomOf="@id/guide_line1"
        app:layout_constraintStart_toStartOf="@id/guide_line" />

    <!--button2 上下居中,并且左侧依赖于guide_line的辅助线显示-->
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@id/guide_line"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

上面的XML代码中,我们添加了两个GuideLine辅助线,button1的位置在两个辅助线的交点处,button2左侧依赖于guide_line的辅助线显示并且上下居中显示,实现出来的效果如图:

在这里插入图片描述在这里插入图片描述

在guideLine控件中,通过设置

android:orientation

来区分是竖直还是水平辅助线

总结

到这里,ConstraintLayout的属性大致介绍完成了,写上面的代码示例我们根本就没有使用嵌套布局,这也是ConstraintLayout的另一个比较牛的功能,减少了View层级的嵌套,降低了界面的渲染绘制层,下面总结下本文介绍到的所有的属性

constraint 属性

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
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

MATCH_CONSTRAINT

android:layout_width=”0dp”
android:layout_height=”0dp”

Bias偏移量设置

app:layout_constraintHorizontal_bias
app:layout_constraintVertical_bias

CircularPositioning 圆形定位

app:layout_constraintCircle
app:layout_constraintCircleRadius
app:layout_constraintCircleAngle

Margin

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

Ratio

app:layout_constraintDimensionRatio=”2:1”
app:layout_constraintDimensionRatio=”H,2:1”
app:layout_constraintDimensionRatio=”w,2:1”

Chains(链条)

app:layout_constraintHorizontal_chainStyle 
取值:spread、packed、spread_inside

GuideLine(辅助线)

layout_constraintGuide_begin
layout_constraintGuide_end
layout_constraintGuide_percent
android:orientation 通过这个属性来区分是竖直的还是水平的辅助线