constrainlayout用法总结(一)

       constrainlayout字面之意约束布局,是google推出的用于最大化的解决布局嵌套问题,同时减少布局渲染时间,提升性能的布局。与相对布局Relativelayout有些类似,约束布局的原理与相对布局是一样的,都是根据视图与视图之间的相互依赖,相对父级布局的位置来进行布局的。但是比Relativelayout更加的灵活,功能更加强大。

        该笔记按照几个步骤来进行展开描述,阐释。

  • 开始

     在项目当中的gradle当中添加constraint-layout依赖:

implementation 'com.android.support.constraint:constraint-layout:1.1.2'
  • 新建布局
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


</android.support.constraint.ConstraintLayout>
  • 添加约束

       添加约束的方式常见两种方式:

       手动进行拖拽:将控件拖进布局空间,然后通过constraint-layout为控件提供的课件的操作部件进行约束的添加。这种方式简便快捷,效率较高,一句话android终于有了一种可以抗衡ios的操作,但是给我的感觉说真的还是差那么一点,体验过ios操作的朋友们能够明白我的意思。当然笔者并不建议以拖拽的方式添加约束。笔者的习惯绝对是会去手敲去添加约束的。

      手敲xml:可能有朋友会说,放着简单便捷的操作不用而去手敲,不是自己找麻烦吗?是的你说的很对。但是我就是愿意去找这个麻烦的。首先我手写的方式能够让我更深刻的去理解constraint-layout为我们提供的属性的特性,并且根据组合属性方式去观察展示效果,这个过程是一个最简单有效的去理解记忆属性特点的好方法。有一部分朋友在使用拖拽方式完成布局后基本上不会再去看xml中自动生成的属性了,等到需求界面一旦发生改变的时候,如果不知道具体的属性产生什么效果,那么你绝对会后悔的,其中苦痛自己体会。

首先,先说一下拖拽方式:

这里写图片描述

可以看到,上下左右都有一个小圆圈,这个圆圈就是用来添加约束的。 
四个角的矩形,是用来扩大或缩小控件的。

这里写图片描述:删除选中控件的所有约束。 
这里写图片描述:编辑基线,用于基线对齐(下面会说)。

现在我们来为这个 Button 添加约束:

这里写图片描述

  • 属性介绍      
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintBaseline_toBaselineOf
  • layout_constraintDimensionRatio
  • layout_constraintHorizontal_weight
  • layout_constraintVertical_weight
  • layout_constraintHorizontal_bias
  • layout_constraintVertical_bias
  • layout_constraintHorizontal_chainStyle
  • layout_constraintVertical_chainStyle

      如上面列出来的属性都是我们开发过程中经常需要用到的属性,大家还可以注意到上面的属性我分别用不同的几种颜色标注了。那么我们就来一一的解读吧。

  首先看红色的部分,这部分的属性跟相对布局(Relativelayout)比较类似,例如app:layout_constraintRight_toLeftOf="@+id/idview"意思为当前控件的右侧在其他控件的左侧,其他的此类属性都是类似的意思。那么最简单的我们想布局中拖入一个控件例如button:

 <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:text="button"/>

   大家肯定注意到了其中的四个属性后面的值是“parent”,这样的四个属性同时作用下,控件button居于父级布局的中央。大家可能有疑问,为什么控件button不在父布局的左上角。constraint-layout约束布局,如果我们只添加左侧或者顶部的属性那么效果会是怎么样呢? 

只添加左上约束:此时的button就出现了停留在左上角的位置,当然如果添加其他的属性,大家可自行实验。

此时我们在顶部在次添加一个button。

 <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="button"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toRightOf="parent"
        android:text="button"/>

我们想实现一个button1在左侧,然后button占满右侧空间,如上代码所示却并不能得到我们想要的结果,上述代码的效果是

而想要达到这样的效果我们button2的宽度需要修改为0dp效果即为:

<Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="button"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toRightOf="parent"
        android:text="button"/>

你会发现button2,好像疯了一样,我们设置的在button1右侧,和与parent右侧对齐完全失效了!!!

别怕,接下来就让你认识到为什么这个控件叫做constraint-layout

在当控件有自己设置的宽度,例如warp_content、固定值时,我们为控件添加的都是约束“Constraint”,这个约束有点像橡皮筋一样会拉这个控件,但是并不会改变控件的尺寸(RL很明显不是这样的)。

例如上例,当button2的宽度较小时,我们为其左侧设置了一个约束(button1右侧),右侧设置了一个约束(parent右侧对其),当两个约束同时生效的时候(你可以认为两边都是相同的一个拉力),button2会居中。

当btn02特别大的时候,依然是这两个力,那么会发生什么?会造成左侧和右侧超出的距离一样大。

那么现在大家肯定有些疑问:

  • 怎么样才能和上面的RL一样,宽度刚好占据剩下的距离呢(btn01右侧到屏幕右侧的距离)?

这个问题,问得很好,我们刚才所有的尝试都是在控件自身拥有特定的宽度情况下执行的;那么如果希望控件的宽度根据由约束来控件,不妨去掉这个特定的宽度,即设置为0试试?

对!当我们将btn02的宽度设置为0时,一切又变得很完美

大家可能疑惑为什么match_parent不是将控件填满剩下的水平空间呢,之前我也想不明白,但是我查阅了官方资料,如下

那么这里,你可能会问0值是什么含义,其实在ConstraintLayout中0代表:MATCH_CONSTRAINT,看到这个常量,是不是瞬间觉得好理解了一点。

  • 最后一个问题,MATCH_PARENT哪去了?

看官网的解释:

Important: MATCH_PARENT is not supported for widgets contained in a ConstraintLayout, though similar behavior can be defined by using MATCH_CONSTRAINT with the corresponding left/right or top/bottom constraints being set to “parent”.`

所以你可以认为:在ConstraintLayout中已经不支持MATCH_PARENT这个值了,你可以通过MATCH_CONSTRAINT配合约束实现类似的效果。当然在我们在将button2的宽度设为wrap_content时候,button2却位于右侧的中央部分,产生这种情况的原因是因为在constraint-layout中每个控件的属性设置当中默认都包含两个属性:

  • layout_constraintHorizontal_bias
  • layout_constraintVertical_bias

他们表示的意思就是控件在设置了水平或者垂直方向上的约束后,表示在水平或者垂直方向的拉力的大小,默认不添加这两个属性的话,他们的默认值是两个方向都是50%,即0.5。如果两侧拉力不是0.5,那么就不是位于中间的位置,请大家自行实践。

好了,到这里,目前我们已经看到其已经和RelativeLayout势均力敌了,接下来我们看一下RL做不到的特性

 现在的要求是我们要做一个banner,宽高比为16:9,如果在之前的话我们只能在代码中动态设置宽高比,可是呢constraint-layout在我们xml里面设置一个属性就可以实现了。

layout_constraintDimensionRatio

没错就是这个属性,使用的时候

 <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintDimensionRatio="16:6"
        android:text="button"/>

那么这样启动的作用就是宽高比为16:6当然控件的宽高都是 MATCH_CONSTRAINT即0dp。写法可以是app:layout_constraintDimensionRatio="H,16:6"或者是app:layout_constraintDimensionRatio="W,16:6",这就是宽高方向上的比例。效果就是

下面我们再来看如果我要做一个tab,怎么做呢?

<TextView
        android:id="@+id/tab1"
        android:layout_width="0dp"
        android:layout_height="30dp"
        android:background="#f67"
        android:gravity="center"
        android:text="Tab1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tab2" />


    <TextView
        android:id="@+id/tab2"
        android:layout_width="0dp"
        android:layout_height="30dp"
        android:background="#A67"
        android:gravity="center"
        android:text="Tab2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@id/tab1"
        app:layout_constraintRight_toLeftOf="@+id/tab3" />


    <TextView
        android:id="@+id/tab3"
        android:layout_width="0dp"
        android:layout_height="30dp"
        android:background="#767"
        android:gravity="center"
        android:text="Tab3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@id/tab2"
        app:layout_constraintRight_toRightOf="parent" />

看下效果:

 

我们设置了tab的左右两两依赖,并且都是设置了宽度0dp,我们实现了等分的效果,使用text冒充tab成功了。

当然大家都知道我们通过linearlayout配合weight也可以实现这样的效果。是的constraint-layout同样支持这样的效果。这个属性就是app:layout_constraintHorizontal_weight,app:layout_constraintVertical_weight见名知意,假设我把他们设置为2,1,1那么效果就是:

大家都看到了到这里constraint-layout是可以达到了relativelayout和linearlayout同样的效果,可以使用constraint-layout替代他们。当然还有一些特性是相对布局与线性布局不可达到的特性。

copy一下官方文档:

Chain heads

Chains are controlled by attributes set on the first element of the chain (the "head" of the chain):

 
Fig. 10 - Chain Head

The head is the left-most widget for horizontal chains, and the top-most widget for vertical chains.

Chain Style

When setting the attribute layout_constraintHorizontal_chainStyle or layout_constraintVertical_chainStyle on the first element of a chain, the behavior of the chain will change according to the specified style (default is CHAIN_SPREAD).

  • CHAIN_SPREAD -- the elements will be spread out (default style)
  • Weighted chain -- in CHAIN_SPREAD mode, if some widgets are set to MATCH_CONSTRAINT, they will split the available space
  • CHAIN_SPREAD_INSIDE -- similar, but the endpoints of the chain will not be spread out
  • CHAIN_PACKED -- the elements of the chain will be packed together. The horizontal or vertical bias attribute of the child will then affect the positioning of the packed elements

 

 
Fig. 11 - Chains Styles

横向的相当于组成了一个链chains,同时配合上weight可以实现上图所示的效果。

chains styles:

  • layout_constraintHorizontal_chainStyle
  • layout_constraintVertical_chainStyle

前提是需要配合app:layout_constraintHorizontal_weight

1.spread + 宽度0dp   效果既是等分的效果并且占满各自的空间

2.spread + 宽度非0  

3.spread_inside + 宽度非0 

4.packed + 宽度非0

以上的条件都是宽度非0的情况下实现的效果。

下面一个属性为:layout_constraintBaseline_toBaselineOf

这个属性是对其两个控件文本部分,这个属性就不在详细的去说了。

下面还有一个叫做android.support.constraint.Guideline,这个类使用起来较为简单。

所以其有个属性为:

android:orientation取值为”vertical”和”horizontal”.

除此以外,还差个属性,决定该辅助线的位置:

  • layout_constraintGuide_begin
  • layout_constraintGuide_end
  • layout_constraintGuide_percent

可以通过上面3个属性其中之一来确定属性值位置。

begin=30dp,即可认为距离顶部30dp的地方有个辅助线,根据orientation来决定是横向还是纵向。

end=30dp,即为距离底部。 
percent=0.8即为距离顶部80%。

好了,下面看一个例子,刚才我们的浮点按钮,我决定通过两根辅助线来定位,一根横向距离底部80%,一个纵向距离顶部80%,浮点按钮就定位在他们交叉的地方。

<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.8" />


    <android.support.constraint.Guideline
        android:id="@+id/guideline_w"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.8" />

    <TextView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="#612"
        app:layout_constraintLeft_toRightOf="@id/guideline_w"
        app:layout_constraintTop_toBottomOf="@id/guideline_h" />

看下效果图吧:

到这里constraint-layout的用法即属性总结了差不多了,后续还有一些属性的用法会陆续添加上来。 

       

ConstraintLayoutAndroid开发中的一种布局方式,它通过将控件彼此约束来定义它们的位置关系,这使得布局更加灵活和扁平化。以下是一些常用的ConstrainLayout属性: 1. app:layout_constraintStart_toStartOf:将控件的起始边缘约束到另一个控件的起始边缘或者父容器的起始边缘。 2. app:layout_constraintEnd_toEndOf:将控件的结束边缘约束到另一个控件的结束边缘或者父容器的结束边缘。 3. app:layout_constraintTop_toTopOf:将控件的顶部边缘约束到另一个控件的顶部边缘或者父容器的顶部边缘。 4. app:layout_constraintBottom_toBottomOf:将控件的底部边缘约束到另一个控件的底部边缘或者父容器的底部边缘。 5. app:layout_constraintLeft_toLeftOf:将控件的左边缘约束到另一个控件的左边缘或者父容器的左边缘。 6. app:layout_constraintRight_toRightOf:将控件的右边缘约束到另一个控件的右边缘或者父容器的右边缘。 7. app:layout_constraintWidth_default:设置控件宽度的默认行为,如"wrap"表示包裹内容,"match"表示匹配约束。 8. app:layout_constraintHeight_default:设置控件高度的默认行为,与app:layout_constraintWidth_default类似。 9. app:layout_constraintHorizontal_bias:设置控件在其约束维度内的水平偏移比例。 10. app:layout_constraintVertical_bias:设置控件在其约束维度内的垂直偏移比例。 11. app:layout_constraintWidth_percent:通过百分比设置控件的宽度,需要和水平约束一起使用。 12. app:layout_constraintHeight_percent:通过百分比设置控件的宽度,需要和垂直约束一起使用。 使用这些属性可以非常灵活地控制布局中各个元素的位置和尺寸,实现复杂的布局需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值