updatePostLayout会在 onLayout 之后调用,在这里做动画就可以。

有了CircularRevealHelper之后可以直接在 xml 里面使用,在CircularRevealHelper的constraint/_referenced/_ids里面指定需要做动画 view。

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

<ImageView
    android:id="@+id/img_mario"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@drawable/mario" />

<cn.feng.constraintLayout2.helps.CircularRevealHelper
    android:id="@+id/helper"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:constraint_referenced_ids="img_mario"
    tools:ignore="MissingConstraints" />

</android.support.constraint.ConstraintLayout>


后面如果要对 view 做CircularReveal直接在 xml 里面指定就可以了,做到了很好的复用。

#### FlyinHelper

![](https://s2.51cto.com/images/20210827/1630060353400068.jpg)

再来看看这个 Flyin 的飞入效果,view 从四周飞入到各自的位置。

这个动画的关键在于计算出每个 view 该从什么方向飞入。

![](https://s2.51cto.com/images/20210827/1630060354756760.jpg)

红色边框的位置可以借助前面介绍的的Layer找到(当然也可以[不借助Layer,自己算](https://gitee.com/vip204888/android-p7),稍显复杂),从而计算出红色框框部分的中间点位置, 再和图中每个 view 的中间点比较(图中每个白点的位置)从而得出每个 view 该从哪个方向飞入。

计算每个view 的初始位置代码如下,借助上面的图形应该很好理解。

for (view in views) {

        val viewCenterX = (view.left + view.right) / 2
        val viewCenterY = (view.top + view.bottom) / 2

        val startTranslationX = if (viewCenterX < centerPoint.x) -2000f else 2000f
        val startTranslationY = if (viewCenterY < centerPoint.y) -2000f else 2000f

        view.translationX = (1 - animatedFraction) * startTranslationX
        view.translationY = (1 - animatedFraction) * startTranslationY
    } 

FlyinHelper 的完整代码[参考这里](https://gitee.com/vip204888/android-p7)

#### ComposeMultipleHelper

每个 view 不但可以接受一个ConstraintHelper,还可以同时接受多个ConstraintHelper。

![](https://s2.51cto.com/images/20210827/1630060355529540.jpg)

左边的四个 ImageView 和右下的 FloatingActionButton 都有 Flyin 的效果,同时左边的四个ImageView还在绕 Y 轴做 3D 旋转。上方的 Seekbar的背景在做CircularReveal的效果。有了前面编写的CircularRevealHelper以及 FlyInHelper 我们可以很方便做到这样的效果。

[代码参考这里](https://gitee.com/vip204888/android-p7)

Flow (VirtualLayout)
--------------------

Flow 是 VirtualLayout,Flow 可以像 Chain 那样帮助快速横向/纵向布局constraint/_referenced/_ids里面的元素。 通过flow/_wrapMode可以指定具体的排列方式,有三种模式

*   wrap none : 简单地把constraint/_referenced/_ids里面的元素组成chain,即使空间不够

![](https://s2.51cto.com/images/20210827/1630060355738133.jpg)

*   wrap chain : 根据空间的大小和元素的大小组成一条或者多条 chain

![](https://s2.51cto.com/images/20210827/1630060356980973.jpg)

*   wrap aligned : wrap chain类似,但是会对齐

![](https://s2.51cto.com/images/20210827/1630060357948849.jpg)

下面看下如何实现这个计算器布局:

![](https://s2.51cto.com/images/20210827/1630060357789464.jpg)```
<?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=".activity.MainActivity">

    <android.support.constraint.helper.Flow
        android:id="@+id/flow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFC107"
        android:padding="20dp"
        app:constraint_referenced_ids="tv_num_7,tv_num_8,tv_num_9,tv_num_4,tv_num_5,tv_num_6,tv_num_1,tv_num_2,tv_num_3,tv_num_0,tv_operator_div,tv_dot,tv_operator_times"
        app:flow_horizontalGap="10dp"
        app:flow_maxElementsWrap="3"
        app:flow_verticalGap="10dp"
        app:flow_wrapMode="aligned"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/tv_num_7"
        style="@style/text_view_style"
        android:text="7" />

    <TextView
        android:id="@+id/tv_num_8"
        style="@style/text_view_style"
        android:text="8" />

    <TextView
        android:id="@+id/tv_num_9"
        style="@style/text_view_style"
        android:text="9" />

    <TextView
        android:id="@+id/tv_num_4"
        style="@style/text_view_style"
        android:text="4" />

    <TextView
        android:id="@+id/tv_num_5"
        style="@style/text_view_style"
        android:text="5" />

    <TextView
        android:id="@+id/tv_num_6"
        style="@style/text_view_style"
        android:text="6" />

    <TextView
        android:id="@+id/tv_num_1"
        style="@style/text_view_style"
        android:text="1" />

    <TextView
        android:id="@+id/tv_num_2"
        style="@style/text_view_style"
        android:text="2" />

    <TextView
        android:id="@+id/tv_num_3"
        style="@style/text_view_style"
        android:text="3" />

    <TextView
        android:id="@+id/tv_num_0"
        style="@style/text_view_style"
        android:text="0" />

    <TextView
        android:id="@+id/tv_operator_div"
        style="@style/text_view_style"
        android:text="/"
        tools:layout_editor_absoluteX="156dp"
        tools:layout_editor_absoluteY="501dp" />

    <TextView
        android:id="@+id/tv_operator_times"
        style="@style/text_view_style"
        android:text="*" />

    <TextView
        android:id="@+id/tv_dot"
        style="@style/text_view_style"
        android:text="."
        tools:layout_editor_absoluteX="278dp"
        tools:layout_editor_absoluteY="501dp" />

    <TextView
        android:id="@+id/KE"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#00BCD4"
        android:gravity="center"
        android:text="Compute"
        android:textColor="@android:color/white"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="@+id/tv_operator_times"
        app:layout_constraintEnd_toEndOf="@+id/tv_dot"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="@+id/tv_operator_div"
        app:layout_constraintTop_toTopOf="@+id/tv_operator_times" />

    <TextView
        android:id="@+id/KR"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#03A9F4"
        android:gravity="right|center_vertical"
        android:paddingEnd="16dp"
        android:text="0"
        android:textColor="@android:color/white"
        android:textSize="58sp"
        app:layout_constraintBottom_toTopOf="@+id/flow"
        app:layout_constraintEnd_toEndOf="@+id/flow"
        app:layout_constraintStart_toStartOf="@+id/flow"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout> 

借助 flow 很快可以布局出来,这里flow_wrapMode使用的是aligned,id 为KE的TextView可以对齐到 Flow 里面的 view,id 为KR的TextView可以对齐到 Flow,另外 Flow 也是ConstraintHelper,所以Flow 也是个 View,可以设置背景,padding等元素。 那么这样布局有什么优势? 这样的布局 view 都在一个层级,不使用 ViewGroup,减少层级。

流式 APIs

1.1 之前需要这样修改属性

 val set = ConstraintSet()
        set.clone(constraintLayout)
        set.setTranslationZ(R.id.image, 32f)
        set.setMargin(R.id.image, ConstraintSet.START, 43)
        set.applyTo(constraintLayout) 

2.0 提供了ConstraintProperties 可以使用流式 API 修改属性

 val properties = ConstraintProperties(findViewById(R.id.image))
        properties.translationZ(32f)
                .margin(ConstraintSet.START, 43)
                .apply() 

MotionLayout

关于 MotionLayout 可以参考ConstraintLayout开发者 Nicolas Roard 写的系列文章,

最后

文章不易,如果大家喜欢这篇文章,或者对你有帮助希望大家多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

由于文章篇幅问题 查看详细文章以及获取学习笔记链接:前往我的腾讯文档领取

  • Android进阶学习全套手册
    关于实战,我想每一个做开发的都有话要说,对于小白而言,缺乏实战经验是通病,那么除了在实际工作过程当中,我们如何去更了解实战方面的内容呢?实际上,我们很有必要去看一些实战相关的电子书。目前,我手头上整理到的电子书还算比较全面,HTTP、自定义view、c++、MVP、Android源码设计模式、Android开发艺术探索、Java并发编程的艺术、Android基于Glide的二次封装、Android内存优化——常见内存泄露及优化方案、.Java编程思想 (第4版)等高级技术都囊括其中。

ConstraintLayout 2,深入浅出Android开发

  • Android高级架构师进阶知识体系图
    关于视频这块,我也是自己搜集了一些,都按照Android学习路线做了一个分类。按照Android学习路线一共有八个模块,其中视频都有对应,就是为了帮助大家系统的学习。接下来看一下导图和对应系统视频吧!!!
    ConstraintLayout 2,深入浅出Android开发

  • Android对标阿里P7学习视频

ConstraintLayout 2,深入浅出Android开发

  • BATJ大厂Android高频面试题
    这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等
    ConstraintLayout 2,深入浅出Android开发