1. 基于 Motion Editor (二) 直线,曲线,周期 添加
Motion Editor (二) 直线,曲线,周期https://blog.csdn.net/u011193452/article/details/127451163
2. 旋转动画
2.1 布局转换为 MotionLayout 布局,文件 fragment_rotation.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/fragment_rotation_scene"
tools:context=".ui.RotationFragment">
<ImageView
android:id="@+id/imageView"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:src="@drawable/ic_rotation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<View
android:id="@+id/rotationTop"
android:layout_width="wrap_content"
android:layout_height="200dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/rotationBottom"
android:layout_width="wrap_content"
android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
2.2 自动生成动画场景文件 fragment_rotation_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:autoTransition="jumpToStart"
motion:constraintSetEnd="@+id/simple"
motion:constraintSetStart="@id/start"
motion:duration="3000">
<KeyFrameSet>
<KeyAttribute
android:rotation="14000"
motion:framePosition="100"
motion:motionTarget="@+id/imageView" />
</KeyFrameSet>
<OnClick motion:targetId="@id/rotationTop" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/imageView"
android:layout_width="320dp"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/simple" />
<ConstraintSet
android:id="@+id/complex"
motion:deriveConstraintsFrom="@+id/start" />
<Transition
motion:autoTransition="jumpToStart"
motion:constraintSetEnd="@+id/complex"
motion:constraintSetStart="@+id/start"
motion:duration="3000">
<KeyFrameSet>
<KeyAttribute
android:rotation="7200"
motion:framePosition="100"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:rotationY="0"
motion:framePosition="100"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:rotationY="0"
motion:framePosition="50"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:rotationY="40"
motion:framePosition="25"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:rotationY="-40"
motion:framePosition="75"
motion:motionTarget="@+id/imageView" />
</KeyFrameSet>
<OnClick motion:targetId="@id/rotationBottom" />
</Transition>
<ConstraintSet
android:id="@+id/cycle"
motion:deriveConstraintsFrom="@+id/start" />
<Transition
motion:constraintSetEnd="@+id/cycle"
motion:constraintSetStart="@+id/start"
motion:duration="2000">
<OnClick />
<KeyFrameSet>
<KeyCycle
android:rotation="180"
motion:framePosition="100"
motion:motionTarget="@+id/imageView"
motion:waveOffset="0"
motion:wavePeriod="1" />
</KeyFrameSet>
</Transition>
</MotionScene>
3. 摆荡动画
3.1 布局文件转换为 MotionLayout 布局,fragment_swing.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/fragment_swing_scene"
tools:context=".ui.SwingFragment">
<ImageView
android:id="@+id/imageView"
android:layout_width="240dp"
android:layout_height="240dp"
android:src="@drawable/ic_rotation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.motion.widget.MotionLayout>
3.2 自动生成动画场景文件,fragment_swing_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:autoTransition="animateToStart"
motion:constraintSetEnd="@+id/one"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyTimeCycle
android:translationX="100dp"
motion:framePosition="100"
motion:motionTarget="@+id/imageView"
motion:waveOffset="0"
motion:wavePeriod="1" />
<KeyTimeCycle
android:rotation="60"
motion:framePosition="100"
motion:motionTarget="@+id/imageView"
motion:waveOffset="0"
motion:wavePeriod="1" />
<KeyAttribute
android:translationY="0dp"
motion:framePosition="50"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:translationY="50dp"
motion:framePosition="25"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:translationY="50dp"
motion:framePosition="75"
motion:motionTarget="@+id/imageView" />
<KeyAttribute
android:translationY="0dp"
motion:framePosition="100"
motion:motionTarget="@+id/imageView" />
</KeyFrameSet>
<OnClick />
</Transition>
<ConstraintSet android:id="@+id/start" />
<ConstraintSet android:id="@+id/one" />
</MotionScene>
4. 过渡动画
4.1 布局转换为 MotionLayout 布局,fragment_transition.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/fragment_transition_scene"
tools:context=".ui.TransitionFragment"
tools:ignore="ContentDescription">
<ImageView
android:id="@+id/imageView1"
android:layout_width="130dp"
android:layout_height="130dp"
android:src="@drawable/ic_baseline_sailing"
app:layout_constraintBottom_toBottomOf="@+id/imageView2"
app:layout_constraintEnd_toStartOf="@+id/imageView2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/imageView2" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginBottom="24dp"
android:src="@drawable/ic_baseline_flight"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/imageView1" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="130dp"
android:layout_height="130dp"
android:src="@drawable/ic_baseline_toys"
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
app:layout_constraintEnd_toStartOf="@+id/imageView4"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/imageView4" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="24dp"
android:src="@drawable/ic_baseline_two_wheeler"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/imageView3"
app:layout_constraintTop_toTopOf="@+id/guideline" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.motion.widget.MotionLayout>
4.2 自动生成动画场景文件 fragment_transition_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/one"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyAttribute
android:scaleX="1.5"
motion:framePosition="100"
motion:motionTarget="@+id/imageView1" />
<KeyAttribute
android:scaleY="1.5"
motion:framePosition="100"
motion:motionTarget="@+id/imageView1" />
</KeyFrameSet>
<OnClick motion:targetId="@id/imageView1" />
</Transition>
<ConstraintSet android:id="@+id/start" />
<ConstraintSet android:id="@+id/one">
<Constraint
android:id="@+id/imageView1"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/imageView2"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginBottom="24dp"
android:alpha="0"
motion:layout_constraintBottom_toTopOf="@+id/guideline"
motion:layout_constraintEnd_toEndOf="@+id/imageView4" />
<Constraint
android:id="@+id/imageView3"
android:layout_width="130dp"
android:layout_height="130dp"
android:alpha="0"
motion:layout_constraintBottom_toBottomOf="@+id/imageView4"
motion:layout_constraintEnd_toStartOf="@+id/imageView4"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@+id/imageView4" />
<Constraint
android:id="@+id/imageView4"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="24dp"
android:alpha="0"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toEndOf="@+id/imageView3"
motion:layout_constraintTop_toTopOf="@+id/guideline" />
</ConstraintSet>
<ConstraintSet
android:id="@+id/two"
motion:deriveConstraintsFrom="@+id/start">
<Constraint
android:id="@+id/imageView2"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/imageView1"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginBottom="48dp"
android:visibility="invisible"
motion:layout_constraintBottom_toTopOf="@+id/imageView3"
motion:layout_constraintStart_toStartOf="@+id/imageView3" />
<Constraint
android:id="@+id/imageView3"
android:layout_width="130dp"
android:layout_height="130dp"
android:visibility="invisible"
motion:layout_constraintBottom_toBottomOf="@+id/imageView4"
motion:layout_constraintEnd_toStartOf="@+id/imageView4"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@+id/imageView4" />
<Constraint
android:id="@+id/imageView4"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="24dp"
android:visibility="invisible"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toEndOf="@+id/imageView3"
motion:layout_constraintTop_toTopOf="@+id/guideline" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@+id/two"
motion:constraintSetStart="@+id/start"
motion:duration="1000">
<OnClick motion:targetId="@id/imageView2" />
<KeyFrameSet>
<KeyAttribute
android:scaleX="1.5"
motion:framePosition="100"
motion:motionTarget="@id/imageView2" />
<KeyAttribute
android:scaleY="1.5"
motion:framePosition="100"
motion:motionTarget="@id/imageView2" />
</KeyFrameSet>
</Transition>
<ConstraintSet
android:id="@+id/three"
motion:deriveConstraintsFrom="@+id/start">
<Constraint
android:id="@+id/imageView4"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="24dp"
android:visibility="invisible"
motion:layout_constraintStart_toStartOf="@+id/imageView2"
motion:layout_constraintTop_toTopOf="@+id/guideline" />
<Constraint
android:id="@+id/imageView3"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/imageView1"
android:layout_width="130dp"
android:layout_height="130dp"
android:visibility="invisible"
motion:layout_constraintBottom_toBottomOf="@+id/imageView2"
motion:layout_constraintEnd_toStartOf="@+id/imageView2"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@+id/imageView2" />
<Constraint
android:id="@+id/imageView2"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginBottom="24dp"
android:visibility="invisible"
motion:layout_constraintBottom_toTopOf="@+id/guideline"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toEndOf="@+id/imageView1" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@+id/three"
motion:constraintSetStart="@+id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyAttribute
android:scaleX="1.5"
motion:framePosition="100"
motion:motionTarget="@+id/imageView3" />
<KeyAttribute
android:scaleY="1.5"
motion:framePosition="100"
motion:motionTarget="@id/imageView3" />
</KeyFrameSet>
<OnClick motion:targetId="@id/imageView3" />
</Transition>
<ConstraintSet
android:id="@+id/four"
motion:deriveConstraintsFrom="@+id/start">
<Constraint
android:id="@+id/imageView4"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/imageView3"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="48dp"
android:visibility="invisible"
motion:layout_constraintStart_toStartOf="@+id/imageView1"
motion:layout_constraintTop_toBottomOf="@+id/imageView1" />
<Constraint
android:id="@+id/imageView1"
android:layout_width="130dp"
android:layout_height="130dp"
android:visibility="invisible"
motion:layout_constraintBottom_toBottomOf="@+id/imageView2"
motion:layout_constraintEnd_toStartOf="@+id/imageView2"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@+id/imageView2" />
<Constraint
android:id="@+id/imageView2"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginBottom="24dp"
android:visibility="invisible"
motion:layout_constraintBottom_toTopOf="@+id/guideline"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintHorizontal_bias="0.5"
motion:layout_constraintStart_toEndOf="@+id/imageView1" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@+id/four"
motion:constraintSetStart="@+id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyAttribute
android:scaleX="1.5"
motion:framePosition="100"
motion:motionTarget="@+id/imageView4" />
<KeyAttribute
android:scaleY="1.5"
motion:framePosition="100"
motion:motionTarget="@+id/imageView4" />
</KeyFrameSet>
<OnClick motion:targetId="@id/imageView4" />
</Transition>
<ConstraintSet
android:id="@+id/staggedJump"
motion:deriveConstraintsFrom="@+id/start">
<Constraint
android:id="@+id/imageView1"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toTopOf="@+id/imageView2"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/imageView2"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintStart_toEndOf="@+id/imageView1"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/imageView3"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toStartOf="@+id/imageView1"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/imageView4"
android:layout_width="130dp"
android:layout_height="130dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toBottomOf="@+id/imageView3" />
</ConstraintSet>
<Transition
motion:constraintSetEnd="@+id/staggedJump"
motion:constraintSetStart="@+id/start">
<OnSwipe motion:dragDirection="dragDown" />
</Transition>
<Transition
motion:constraintSetEnd="@+id/side"
motion:constraintSetStart="@+id/start"
motion:duration="1000">
<KeyFrameSet>
<KeyAttribute
android:scaleX="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView1" />
<KeyAttribute
android:scaleY="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView1" />
<KeyAttribute
android:scaleX="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView2" />
<KeyAttribute
android:scaleY="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView2" />
<KeyAttribute
android:scaleX="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView3" />
<KeyAttribute
android:scaleY="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView3" />
<KeyAttribute
android:scaleX="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView4" />
<KeyAttribute
android:scaleY="0.6"
motion:framePosition="100"
motion:motionTarget="@+id/imageView4" />
</KeyFrameSet>
<OnSwipe motion:dragDirection="dragStart" />
</Transition>
<ConstraintSet
android:id="@+id/side"
motion:deriveConstraintsFrom="@+id/start">
<Constraint
android:id="@+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
motion:layout_constraintBottom_toTopOf="@+id/imageView2"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/imageView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
motion:layout_constraintBottom_toTopOf="@+id/guideline"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/imageView3"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toBottomOf="@+id/imageView4" />
<Constraint
android:id="@+id/imageView4"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="@+id/guideline" />
</ConstraintSet>
<ConstraintSet
android:id="@+id/hide"
motion:deriveConstraintsFrom="@+id/side" />
<Transition
motion:constraintSetEnd="@+id/hide"
motion:constraintSetStart="@+id/side"
motion:duration="1000">
<OnSwipe motion:dragDirection="dragStart" />
<KeyFrameSet>
<KeyAttribute
android:translationX="-200dp"
motion:framePosition="100"
motion:motionTarget="@+id/imageView1" />
<KeyAttribute
android:translationX="-200dp"
motion:framePosition="100"
motion:motionTarget="@+id/imageView2" />
<KeyAttribute
android:translationX="-200dp"
motion:framePosition="100"
motion:motionTarget="@+id/imageView3" />
<KeyAttribute
android:translationX="-200dp"
motion:framePosition="100"
motion:motionTarget="@+id/imageView4" />
</KeyFrameSet>
</Transition>
</MotionScene>
5. 效果动图