MotionLayout 基础
motionDebug
新建一个 MotionLayout 布局
activity_basic_motion_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<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_basic_motion_layout_scene"
app:motionDebug="SHOW_ALL"
tools:context=".BasicMotionLayoutActivity">
<View
android:id="@+id/view"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FF9E80"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
添加 app:motionDebug="SHOW_ALL",运行的时候就会在屏幕底端显示一些调试信息比如进度、状态、路径等。
activity_base_motion_layout_scene.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:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="2000">
<KeyFrameSet></KeyFrameSet>
<OnClick motion:targetId="@+id/view" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@+id/view">
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@+id/view">
<Layout
android:layout_width="100dp"
android:layout_height="100dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent" />
</Constraint>
</ConstraintSet>
</MotionScene>
注意,<Constraint> 标签,之前我们的做法是直接把布局参数写在 <Constraint> 里面的,现在是写在 <Constraint> 里面的 <Layout> 标签里。
这里要注意的是,就算只是改变一个布局参数,其他的布局参数也要写上,也就是说原来控件宽高都是 100dp,想改变 height 为 200dp,width 不变,android:layout_width="100dp" 也是不能够省略的,其他的布局参数也同理。
pathMotionArc
目前为止,MotionLayout 的运动路径都是直线的,我们可以通过在开始场景里的 <Constraint> 添加一个 <Motion> 标签来配置运动的路径。
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@+id/view">
<Motion motion:pathMotionArc="startVertical" />
</Constraint>
</ConstraintSet>
插值器
还可以通过 motion:transitionEasing 来控制动画的节奏
accelerate:加速,一般用于入场decelerate:减速,一般用于出场
<Constraint>里的transitionEasing属性值应该在Start场景中指定,在End场景中指定是无效的。
与 motion:transitionEasing 比较相似的一个属性是
<Constraint>里的transitionEasing与<Transition>的motionInterpolator都是用来定义过渡动画的插值器的。但<Constraint>元素的transitionEasing属性定义的是单独某个View的过渡动画的插值器,而<Transition>里的motionInterpolator定义的是整个过渡动画的插值器。
如果为
<Constraint>指定了transitionEasing插值器,这个插值器将与motionInterpolator属性指定的全局插值器同时作用于View的过渡动画,而不是覆盖。
motion:motionInterpolator="bounce" + motion:transitionEasing="accelerate":
motion:motionInterpolator="bounce" + motion:transitionEasing="decelerate":
Transform
除了这些简单的位移动画,MotionLayout 还支持变换动画,它们写在 <Transform> 标签里
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@+id/view">
...
<Transform
android:rotation="360"
android:scaleX="0.5"/>
</Constraint>
</ConstraintSet>
自定义属性
MotionLayout 控件只会检测标准的布局属性,对于其他的属性变动,如 View 的背景颜色变动是无法检测出来的,因此就需要使用自定义属性。
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
...
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@+id/view">
...
<CustomAttribute
motion:attributeName="backgroundColor"
motion:customColorValue="#FF9E80" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@+id/view">
...
<CustomAttribute
motion:attributeName="backgroundColor"
motion:customColorValue="#B388FF" />
</Constraint>
</ConstraintSet>
</MotionScene>
使用 <CustomAttribute> 标签,attributeName 指定属性名,动画过程中,MotionLayout 会通过 get/set + 属性名 反射调用 view 的相关方法。