美文网首页
ConstraintLayout 1.1版本的新特性

ConstraintLayout 1.1版本的新特性

作者: ZHDelete | 来源:发表于2018-11-30 17:04 被阅读16次

转自:
ConstraintLayout 1.1版本的新特性

约束布局ConstraintLayout看这一篇就够了


ConstraintLayout被译为约束布局,推出它旨在避免传统布局绘制界面时,可能会带来的overdraw等问题,在1.1.x版本,较之1.0.x版本推出了一些新功能(之前的介绍,见此篇:ConstraintLayout使用).

本篇使用的Constraint-layout版本如下:

implementation 'com.android.support.constraint:constraint-layout:1.1.3'

1: Circular Position(极坐标定位)

此功能允许元素之间以: 圆心 + 距离 + 角度的方式进行相对定位
更云山雾罩的说是: 以前的定位方式都是基于平面直角坐标系,上下左右+距离定位的,现在允许以极坐标的方式进行定位了
共有3个相关属性:

  • layout_constraintCircle:作为约束中心的控件id
  • layout_constraintCircleAngle:被约束控件距圆心的的距离,即圆的半径
  • layout_constraintCircleRadius:被约束控件 与 圆心 及 向上(statusBar方向)的夹角

举个栗子:

<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">


    <!--
layout_constraintCircle 约束的控件的id
layout_constraintCircleRadius 约束距离圆心的距离,也就是圆的半径
layout_constraintCircleAngle 约束的角度(0-360度)
    -->

    <Button
        android:id="@+id/btn_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintCircle="@id/btn_1"
        app:layout_constraintCircleAngle="30"
        app:layout_constraintCircleRadius="150dp" />

</android.support.constraint.ConstraintLayout>

效果如下:

cir_pos.png

有了这种圆形约束,为我们进行围绕某中心进行旋转,又提供了一致新的动画实现方式,只需要修改ConstraintLayout.LayoutParams的属性circleAngle就行了,比如:

var angle = 0f
val params = btn_2.layoutParams as ConstraintLayout.LayoutParams
btn_1.setOnClickListener {
    angle += 10
    params.circleAngle = angle
    btn_2.layoutParams = params
}

2: Enforcing constraints(最大最小尺寸)

首先我们要知道android:maxWidth,android:maxHeight属性在ConstraintLayout中已经不生效了
当我们控件宽高为: WRAP_CONTENT时,而且想用:maxWidth,maxHeight两个属性来约束控件最大宽高是,要按如下写法:

<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">

<!--
可以看出maxWidth和maxHeight在约束布局里面是不起作用的,在1.1里面就引入了WRAP_CONTENT : enforcing constraints强制约束的属性:

app:layout_constrainedWidth="true|false"
app:layout_constrainedHeight="true|false"
同时加入新的控制最大值最小值的属性:

layout_constraintWidth_min和layout_constraintHeight_min 同minWidth属性
layout_constraintWidth_max和layout_constraintHeight_max 同maxWidth属性
-->

    <!--maxWidth/Height 无效-->
    <ImageView
        android:id="@+id/image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxWidth="10dp"
        android:maxHeight="10dp"
        android:src="@mipmap/antman_2_2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"

        />

     <!--固定宽高,作为参考-->
    <ImageView
        android:id="@+id/image2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@mipmap/antman_2_2"

        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"

        />

     <!--约束 宽高-->
    <ImageView
        android:id="@+id/image3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/antman_2_2"

        app:layout_constrainedWidth="true"
        app:layout_constrainedHeight="true"
        app:layout_constraintWidth_max="50dp"
        app:layout_constraintHeight_max="50dp"

        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"

        />
</android.support.constraint.ConstraintLayout>

效果如下:

constrainted_width_height.png

可以看出在image1里,maxWidthmaxHeight在约束布局里不起作用了,在1.1.x版本里,引入了wrap_content:enforcing constraints强制约束属性:

  • app:layout_constrainedWidth="true|false"
  • app:layout_constrainedHeight="true|false"

同时,加入新的控制最大/最小宽高的属性:

  • layout_constraintWidth_minlayout_constraintHeight_min属性 同minWidth属性,约束最小宽高
  • layout_constraintWidth_maxlayout_constraintHeight_max属性 同maxWidth属性,约束最大宽高

设置新的属性后,显示效果同image3,可以看到,效果同其他布局里的max/minSize是一致的

3:MATCH_CONSTRAINT dimensions(按比例设置尺寸)

还记得我们之前在ConstraintLayout里是如何实现一个控件占满屏幕宽度一半的吗?,是通过GuideLine实现的

在1.1.x之后,添加了3个属性,来实现对MATCH_CONSTRAINT属性的宽高控制:

  • layout_constraintWidth_minlayout_constraintHeight_min属性 同minWidth属性,约束最小宽高
  • layout_constraintWidth_maxlayout_constraintHeight_max属性 同maxWidth属性,约束最大宽高
  • layout_constraintWidth_percentlayout_constraintHeight_percent,按百分比 设置 长宽

下面实现一个控件占满屏幕宽度一半:

<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">

    <!--
    
    在1.1之后添加了三个属性,来实现对MATCH_CONSTRAINT属性的宽高控制:
    
    layout_constraintWidth_min和layout_constraintHeight_min 同minWidth属性
    layout_constraintWidth_max和layout_constraintHeight_max 同maxWidth属性
    layout_constraintWidth_percent和layout_constraintHeight_percent 根据父布局的百分百设置长款
    现在我们实现一个控件实现占屏幕宽度的一半,是什么样子的呢?
    -->

    <Button
        android:id="@+id/btn1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 1------------------------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent="0.5" />


    <Button
        android:id="@+id/btn2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 1------------------------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn1"
        app:layout_constraintWidth_max="100dp" />

    <Button
        android:id="@+id/btn3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="bo"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn2"
        app:layout_constraintWidth_min="200dp" />

    <Button
        android:id="@+id/btn4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="bo"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn3" />

</android.support.constraint.ConstraintLayout>

我们看上面的btn1,通过app:layout_constraintWidth_percent="0.5",实现了宽度为屏幕宽度的一半,无论文字内容长短,宽度一直是屏幕一半的
这种实现方法,是否比GuideLine的实现简单多呐?

上面的 btn2是对app:layout_constraintWidth_max最大宽度的约束,无论内容多么多,宽度最大不超过约束的100dp
上面btn3是对最小宽度的约束,无论内容多么少,宽度都不会小于约束的200dp
btn3是作为参照,不设置任何关于MATCH_CONSTRAINT约束

layout_constraintWidth_default实现 WRAP_CONTENT的效果:
layout_constraintWidth_default的默认值是spread


    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button 1-------------------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
/>
    <Button
        android:id="@+id/btn2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 2---------------------------------------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_default="spread"
        app:layout_constraintWidth_percent="0.5" />


    <Button
        android:id="@+id/btn3"


        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 3------------------------------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn2"
        app:layout_constraintEnd_toEndOf="parent"

        app:layout_constraintWidth_percent="0.5"
 />

    <Button
        android:id="@+id/btn4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 4-----------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_default="wrap"
        app:layout_constraintWidth_percent="0.5"
        />


    <Button
        android:id="@+id/btn5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 5-------------------------------------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn4"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_default="wrap"
        />
    <Button
        android:id="@+id/btn6"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="button 6---------------"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn5"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_default="spread"
        />
<!--
    app:layout_constraintWidth_default="wrap"
    spred
    percent
-->

</android.support.constraint.ConstraintLayout>
  • 1: btn1 -> 默认情况

  • 2: btn2 和 btn3 -> constraintWidth_default默认值是sperate,
    seperate 或不写 + percent 可以固定宽高百分比

  • 3: btn4 ->constraintWidth_default 设为wrap 会使 persent失效,变成wrap_content 的模式

  • 4: btn5 -> width=0dp + wrap能实现 wrap_content的模式

  • 5: btn6 -> width=0dp + spread 能实现match_parent的模式

4:Margins and chains(链中的margin)

在1.1之后,Chains里设置maring属性时,margin值死可以叠加的

<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">


    <!--
        在1.1之后,Chains里面设置margin属性的时候,值是可以叠加的
    -->

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button 1"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_marginEnd="20dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/btn2"
        
        />


    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button 2"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_marginStart="10dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/btn1"

 />
    
</android.support.constraint.ConstraintLayout>
margin_chain.png

5:Barrier

Barrier(屏障)与GuideLine类似,也属于Virtual Helper objects,其属性有:

  • barrierDirection屏障生效方向,值为:top,bottom,start,end,left,right

  • constraint_referenced_ids屏障基于哪些控件生成,多个id,用 逗号 隔开

  • barrierAllowsGoneWidgets 当控制的控件被设置为GONE的时候,则屏障创建会在GONE掉控件已解析的位置上进行创建,默认是true。

笔者注: barrierAllowsGoneWidgets属性,在使用过程中,并没有发现到底有什么用,这个有待更新

barrer_1.png

假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,如下所示:

barrer_2.png

这个时候C只要约束在Barrier的右边就可以了,代码如下:

<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">

    <!--
    此部分 参照:
    https://www.jianshu.com/p/17ec9bd6ca8a
    4.辅助工具
    4.2 Barrier

    https://www.jianshu.com/p/a74557359882
    6、Barrier

    -->

    <TextView
        android:id="@+id/text1"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:text="TextView1"
        android:background="@color/colorAccent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <TextView
        android:id="@+id/text2"
        android:layout_width="120dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="TextView2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text1"
        />

    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierAllowsGoneWidgets="false"
        app:barrierDirection="right"
        app:constraint_referenced_ids="text1,text2" />


    <TextView
        android:id="@+id/text3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView3"
        app:layout_constraintLeft_toRightOf="@id/barrier"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_margin="10dp"
        />

</android.support.constraint.ConstraintLayout>
barrer_show.png

6:Group

Group 可以吧多个控件归为一组,方便隐藏或显示一组控件时,统一调用

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

    <!--
Group
Group与Barrier一样,也是属于Virtual Helper objects。顾名思义,Group一个组的控件,通过设置一组的控件id,来达到分组的目的。
想想这样的情况,在我们针对多个控件进行显示隐藏的时候,通常要写很多的setVisibility的代码,但是在1.1之后,直接设置Group的显示和隐藏就可以了。
    -->

    <TextView
        android:id="@+id/text1"
        android:background="#a9b3a9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="10dp"
        android:text="TextView1" />

    <TextView
        android:id="@+id/text2"
        android:background="#a9b3a9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="TextView2"
        app:layout_constraintStart_toEndOf="@id/text1" />

    <TextView
        android:id="@+id/text3"
        android:background="#a9b3a9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="TextView3"
        app1:layout_constraintStart_toEndOf="@id/text2" />

    <android.support.constraint.Group
        android:id="@+id/group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="text1,text3" />

</android.support.constraint.ConstraintLayout>

我们用Group把TextView1TextView3归为一组,再控制这组控件的可见性,效果如下:

        text1.setOnClickListener {
            group.visibility = if (group.visibility == View.VISIBLE) View.GONE else View.VISIBLE
        }
grop.gif

相关文章

网友评论

      本文标题:ConstraintLayout 1.1版本的新特性

      本文链接:https://www.haomeiwen.com/subject/engccqtx.html