MotionLayout
支持在各种状态之间进行动画处理,需要通过 layoutDescription 属性添加 MotionScene 文件,该文件包含一个顶级标签 “MotionScene”。布局内正常放控件,但内部控件都需要 id,动画处理都要在该文件中进行。
MotionScene 文件内说明
MotionScene 文件是 res/xml/...
下的文件。在使用 MotionLayout 报错时,Alt+Enter 补全缺失方法后会自动生成对应文件和 layoutDescription 属性。可以自己创建文件。
标签 | 描述 |
---|---|
<ConstrainSet> | 约束集 |
<Transition> | ConstrainSet 之间的转换 |
<StateSet> | 系统支持的状态(可选) |
<ViewTransition> | 视图在状态或约束集中的转换 |
至少写两个 ConstraintSet 用于 Start 和 End,在 Transition 使用。MotionLayout 继承的是 ConstraintLayout,可以直接在 ConstraintSet 描述控件,布局文件会对应内容改变。
简单缩放
布局内控件只有一个,实现起来很容易,很好上手。
布局文件
@dimen/box -> 140dp,@dimen/icon -> 70dp
MotionLayout 的 layoutDescription 属性和控件 id 必须要写!
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/box"
android:layout_height="@dimen/box"
app:layoutDescription="@xml/activity_motion_scene">
<ImageView
android:id="@+id/pingpang"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:src="@mipmap/pingpang" />
</androidx.constraintlayout.motion.widget.MotionLayout>
activity_motion_scene.xml
<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/pingpang"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/pingpangEnd">
<Constraint
android:id="@id/pingpang"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:scaleX="2"
android:scaleY="2"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@id/pingpangEnd"
motion:constraintSetStart="@id/start">
<OnClick motion:targetId="@id/pingpang" />
</Transition>
</MotionScene>
- OnClick 点击开始动画
- OnSwipe 滑动运行动画
- targetId 属性,指定动画目标。如果不写点击或滑动 MotionLayout 内的任意位置都能开始动画
多个控件
布局文件
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/box"
android:layout_height="@dimen/box"
app:layoutDescription="@xml/activity_motion_scene">
<ImageView
android:id="@+id/pingpang"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:src="@mipmap/pingpang" />
<ImageView
android:id="@+id/run"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:src="@mipmap/run" />
<ImageView
android:id="@+id/boxing"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:src="@mipmap/boxing" />
<ImageView
android:id="@+id/gymnastics"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:src="@mipmap/gymnastics" />
</androidx.constraintlayout.motion.widget.MotionLayout>
activity_motion_scene.xml
四个控件都是一样的动画效果,我省略了两个控件的动画代码。
<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/pingpang"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/run"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_editor_absoluteY="@dimen/icon" />
<Constraint
android:id="@id/boxing"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/gymnastics"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_editor_absoluteY="@dimen/icon" />
</ConstraintSet>
<ConstraintSet android:id="@+id/pingpangEnd">
<Constraint
android:id="@id/pingpang"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:scaleX="2"
android:scaleY="2"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@id/pingpangEnd"
motion:constraintSetStart="@id/start">
<OnClick motion:targetId="@id/pingpang" />
<KeyFrameSet>
<KeyAttribute
android:alpha="0"
motion:framePosition="80"
motion:motionTarget="@id/run" />
<KeyAttribute
android:alpha="0"
motion:framePosition="80"
motion:motionTarget="@id/boxing" />
<KeyAttribute
android:alpha="0"
motion:framePosition="80"
motion:motionTarget="@id/gymnastics" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@id/run" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@id/boxing" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@id/gymnastics" />
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/runEnd">
<Constraint
android:id="@id/run"
android:layout_width="@dimen/icon"
android:layout_height="@dimen/icon"
android:scaleX="2"
android:scaleY="2"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@id/runEnd"
motion:constraintSetStart="@id/start">
<OnClick motion:targetId="@id/run" />
<KeyFrameSet>
<KeyAttribute
android:alpha="0"
motion:framePosition="80"
motion:motionTarget="@id/pingpang" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@id/pingpang" />
<KeyAttribute
android:alpha="0"
motion:framePosition="80"
motion:motionTarget="@id/boxing" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@id/boxing" />
<KeyAttribute
android:alpha="0"
motion:framePosition="80"
motion:motionTarget="@id/gymnastics" />
<KeyAttribute
android:alpha="0"
motion:framePosition="100"
motion:motionTarget="@id/gymnastics" />
</KeyFrameSet>
</Transition>
... ...
</MotionScene>
KeyFrameSet 关键帧
- KeyPosition
- KeyTrigger
- KeyAttribute
- KeyCycle
- KeyTimeCycle
MotionLayout 的一些属性
属性 | 描述 |
---|---|
layoutDescription | 指定 MotionScene 文件(@xml/...) |
showPaths | 是否显示动画运动路线(布尔值) |
motionDebug | 是否显示动画信息(布尔值) |
motionProgress | 设置动画进度的某个关键点(数值) |