动画作为Android开发里重要部分,在以前,Android 开发者想要实现产品提出动画的需求,会使用属性动画或系统提供的动画库完成,然后编译,发现有点不对劲,再微调,再部署,这样的反反复复经历几轮,无论是开发成本还是学习成本比较大的。最近, 我发现 MotionLayout,可以让整个流程的效率得到提升,但是当我安利给小伙伴时, 会听到他们说,有点难,我猜测,难的原因可能是国内鲜有MotionLayout的教程,今天,我把自己的理解过程分享在这里。
如何实现动画
实现动画的前提,要知道什么是动画
物体从A形态平滑过渡至B形态的过程
所以为了实现动画,我们要从两个方面入手:
- 定义A、B形态
- 找到实现平滑过渡的方式
所以,我们在使用 MotionLayout 过程中,其实就是去寻找以上两个概念如何在 MotionLayout 中落地.
先看效果图:
那 MotionLayout 如何实现上面的效果呢....
MotionLayout
官网是这么介绍的:
MotionLayout is a subclass of ConstraintLayout and offer a mix of features between the property animation framework, TransitionManager, and CoordinatorLayout.
所以,我们可以把 MotionLayout 当做拥有对子控件声明并执行动画的 ConstraintLayout。
那,系统是如何让 MotionLayout 拥有这个能力的? 分别需要了解:
- MotionScene
- Transition
- ConstraintSet
- Constraint
从使用的角度,分别介绍它们。
使用步骤:
引入此库, 不做赘述,详见官网
声明 MotionLayout
- 对已有根布局为
ConstraintLayout的xml, 在 design 模式中,右键呼出菜单,选择 Covert MotionLayout. - 按照普通 ViewGoup 声明即可。
<?xml version="1.0" encoding="utf-8"?>
<!-- activity_main.xml -->
<androidx.constraintlayout.motion.widget.MotionLayout
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:id="@+id/motionLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/scene_01">
<View
android:id="@+id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:background="@color/colorAccent"
android:text="Button" />
</androidx.constraintlayout.motion.widget.MotionLayout>
你应该发现了,上诉描述中的layoutDescription比较陌生,这个属性引用了 scene_01 . 这就是 'MotionScene'
MotionScene 其实是xml文件,下面我们就来看一眼声明的 scene_01.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="1000">
<OnSwipe
motion:touchAnchorId="@+id/button"
motion:touchAnchorSide="right"
motion:dragDirection="dragRight" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="8dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginEnd="8dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
</MotionScene>
简单介绍一下
<Transition> 定义动画执行过程.
motion:constraintSetStart和motion:constraintSetEnd分别定义动画开始和结束状态。这个状态通过Constraint定义。
<OnSwipe>定义触发动画的方式
Constraint 描述执行动画的控件的状态.在上述描述里,start 定义了 button 控件动画的起始的位置.end定义了结束的位置。不难发现,定义方式和使用约束布局是一样的。这大大降低了开发者们学习Constraint的成本。
ConstraintSet通过组织Constraint完成多个控件执行动画。 我们还可以声明以下属性,完成更多的动画效果- alpha
- visibility
- elevation
- rotation, rotationX, rotationY
- translationX, translationY, translationZ
- scaleX, scaleY
所以,当你想要不同的动画, 只需要在 Constraint 中定义你想要的状态,MotionLayout 会帮你平滑的过渡动画.
More
- 可以拿到
MotionLayout对象即可调用相关方法. - Motion Editor 通过可视化界面,可让你享受所见即所得的动画制作过程。