【版权申明】非商业目的注明出处可自由转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/106182408
出自:shusheng007
概述
前段时间升级了Android Studio到4.0, 发现新增了一个动画编辑器的功能,又一次感叹Android开发真的是越来越简单了。看了一下感觉挺有意思,所以就简单上手一下这个动画布局MotionLayout
,通过这个布局我们可以以非常简单的方式作出很炫的动画。
动画布局基本元素
先上一张动图吧,图中的动画使用MotionLayout
不到两分钟就可以完成,在此感谢老婆贡献自己的美照。
我们只要搞清楚几个关键元素,上手就易如反掌了,当然高级特性还需要熟练后深入探索,这个成年人都明白。
我们可以用一句话来描述一个View的动画:此View从开始状态到达结束状态的一个过程
MotionLayout
MotionLayout
是整个动画的容器,正是它提供了让其内部的直接嵌套View
做动画的能力。它是ConstraintLayout
的子类, 可以从AS中通过ConstraintLayout
转换而来。
MotionScene
动画场景,顾名思义,它的作用就是描述整个动画。是一个xml文件,放在xml
文件夹内,作为MotionLayout
的layoutDescription
属性的值,本例中我写了个一个名为activity_motion_scene.xml
的MotionScence文件并设置给MothionLayout
,如下所示
<androidx.constraintlayout.motion.widget.MotionLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
...
app:layoutDescription="@xml/activity_motion_scene">
...
</androidx.constraintlayout.motion.widget.MotionLayout>
ConstraintSet
动画开始时或者结束时的快照,其用来描述一个View开始和结束时候的状态。例如一个View动画开始前在哪里,多大尺寸,什么颜色等等。 其嵌套在MotionScene 里面,一般有两个,一个开始一个结束。
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 动画开始快照-->
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/my_wife"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</ConstraintSet>
<!-- 动画结束快照-->
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/my_wife"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
app:layout_constraintStart_toEndOf="@id/my_wife_left"
app:layout_constraintEnd_toStartOf="@id/my_wife_right"
app:layout_constraintTop_toTopOf="parent"
/>
</ConstraintSet>
...
</MotionScene>
Transition
描述View从开始状态变换到结束状态的过程,且响应用户的操作,其嵌套在MotionScene 里,与ConstraintSet
平级,是整个动画布局的精华部分。
Transition 的constraintSetEnd 属性设置开始ConstraintSet ,constraintSetStart属性设置结束那个ConstraintSet ,再设置一个动画时间即可。
其可以包含一个<KeyFrameSet>
负责在动画过程中改变view的位置和属性。如果不设置此标签,那么我们的动画就会线性的从开始运动到结束。
<Transition
app:constraintSetEnd="@+id/end"
app:constraintSetStart="@id/start"
app:duration="2000">
<KeyFrameSet>
<KeyPosition
app:motionTarget="@id/my_wife_left"
app:framePosition="40"
app:keyPositionType="parentRelative"
app:percentX="0"
/>
...
<KeyAttribute
app:motionTarget="@id/my_wife"
app:framePosition="40"
android:rotationY="360"
/>
</KeyFrameSet>
<OnSwipe
app:touchAnchorId="@+id/my_wife"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
<OnClick app:targetId="@+id/my_wife"
app:clickAction="toggle" />
</Transition>
MotionLayout基础使用
明白了以上几个元素使用就非常简单了,让我们完成文章最开始的动画
- 配置环境
需要升级constraintlayout控件库到2.0以上,现在是beta6了,已经过了alpha,说明接口稳定了。
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta6"
- 具体使用
- 在layout文件中用MotionLayout 包裹需要做动画的View。
<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:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/activity_motion_scene" app:motionDebug="SHOW_PATH" tools:context=".animation.MotionActivity"> <ImageView android:id="@+id/my_wife_left" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/my_wife"/> <ImageView android:id="@+id/my_wife" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/my_wife"/> <ImageView android:id="@+id/my_wife_right" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/my_wife" /> </androidx.constraintlayout.motion.widget.MotionLayout>
- 在res/xml 文件夹中新建一个名为:
activity_motion_scene
的MotionScene文件,并设置到MotionLayout的layoutDescription
属性中 - 在MotionScene中定义两个ConstraintSet,一个为View的开始状态,一个为View结束状态。
- 在MotionScene中定义一个Transition,并设置开始与结束的ConstraintSet 。
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="@+id/end"
app:constraintSetStart="@id/start"
app:duration="2000">
<KeyFrameSet>
<KeyPosition
app:motionTarget="@id/my_wife_left"
app:framePosition="40"
app:keyPositionType="parentRelative"
app:percentX="0"
/>
<KeyPosition
app:motionTarget="@id/my_wife_right"
app:framePosition="40"
app:keyPositionType="parentRelative"
app:percentX="1"
/>
</KeyFrameSet>
<!-- 使动画响应滑动事件-->
<OnSwipe
app:touchAnchorId="@+id/my_wife"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
<!-- 使动画响应点击事件-->
<OnClick app:targetId="@+id/my_wife" app:clickAction="toggle" />
</Transition>
<!-- 动画开始快照-->
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/my_wife"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<Constraint
android:id="@+id/my_wife_left"
android:layout_width="60dp"
android:layout_height="60dp"
android:alpha="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<Constraint
android:id="@+id/my_wife_right"
android:layout_width="60dp"
android:layout_height="60dp"
android:alpha="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</ConstraintSet>
<!-- 动画结束快照-->
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/my_wife_left"
android:layout_width="100dp"
android:layout_height="100dp"
android:alpha="1.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/my_wife"
app:layout_constraintTop_toTopOf="@id/my_wife"
app:layout_constraintBottom_toBottomOf="@id/my_wife"
/>
<Constraint
android:id="@+id/my_wife"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
app:layout_constraintStart_toEndOf="@id/my_wife_left"
app:layout_constraintEnd_toStartOf="@id/my_wife_right"
app:layout_constraintTop_toTopOf="parent"
/>
<Constraint
android:id="@+id/my_wife_right"
android:layout_width="100dp"
android:layout_height="100dp"
android:alpha="1.0"
app:layout_constraintStart_toEndOf="@id/my_wife"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/my_wife"
app:layout_constraintBottom_toBottomOf="@id/my_wife"
/>
</ConstraintSet>
</MotionScene>
经过上面简单的几步动画就已经完成啦,是不是2分钟内就搞定了。
其中, <Transition>
里的<OnClick>
标签响应用户的点击动作,例如此例中我们点击一下中间的view,动画就开始了。
<OnClick app:targetId="@+id/my_wife" app:clickAction="toggle" />
扩展
上面只是可以让你快速上手,里面还有很多高级特性需要你继续探索,例如在Transition的 KeyFrameSet 里面还包括
<KeyCycle>
、<KeyAttribute>
、 <KeyTimeCycle>
、 <KeyTrigger>
等对动画精细控制的标签
下面是一些很好的资源,可以帮助你更加详细的理解这个库
本文源码:AndroidDevMemo
官方示例:ConstraintLayoutExamples
Medium博客: Introduction to MotionLayout
总结
IT 技术更新换代实在是太快了,而且对于应用层会越变越简单,所以奉劝各位可爱的程序员们在习得日常求生技能后,最好还是多关注一下计算机科学基础。例如计算机系统、数据结构、算法、数据库、网络、编译原理、设计模式等
总的来说,照目前的情况来看,未来的社会会更加数字化、智能化,所以程序员会大有可为,加油。
转载:https://blog.csdn.net/ShuSheng0007/article/details/106182408