一.KeyFrameSet实现单个View运动轨迹
1.效果图
2.布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/activity_main_constraintlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<androidx.constraintlayout.motion.widget.MotionLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_constraint_layout_scene_only"
app:motionDebug="SHOW_PATH">
<ImageView
android:id="@+id/imageView"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/football" />
</androidx.constraintlayout.motion.widget.MotionLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
3.描述文件
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 开始ConstraintSet集合 -->
<ConstraintSet android:id="@+id/start">
<!-- 开始位置 imageView 屏幕左上角 -->
<Constraint
android:id="@id/imageView"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<!-- 结束ConstraintSet集合 -->
<ConstraintSet android:id="@+id/end">
<!-- 结束位置 imageView 屏幕底部布局右边位置 -->
<Constraint
android:id="@id/imageView"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</ConstraintSet>
<!-- 动画轨迹 指定开始&结束的ConstraintSet 以及动画持续的时间-->
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@id/start"
app:duration="3000">
<!-- 动画开始的方式是 点击 imageView -->
<OnClick
app:clickAction="toggle"
app:targetId="@id/imageView" />
<!-- KeyFrameSet集合 -->
<KeyFrameSet>
<!-- imageView的轨迹位置 整个运动的[0%,20%] 沿着X轴从开始位置走到屏幕最右边-->
<KeyPosition
app:framePosition="20"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView"
app:pathMotionArc="flip"
app:percentX="1.0"
app:percentY="0.0" />
<!-- ImageView的轨迹位置 整个运动的[20%,40%] -->
<KeyPosition
app:framePosition="40"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView"
app:pathMotionArc="startVertical"
app:percentX="0"
app:percentY="0.3" />
<!-- ImageView的轨迹位置 整个运动的[40%,60%]-->
<KeyPosition
app:framePosition="60"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView"
app:pathMotionArc="startVertical"
app:percentX="1.0"
app:percentY="0.5" />
<!-- ImageView的轨迹位置 整个运动的[60%,80%]-->
<KeyPosition
app:framePosition="80"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView"
app:pathMotionArc="startVertical"
app:percentX="0.1"
app:percentY="0.62" />
<!-- ImageView的轨迹位置 整个运动的[80%,85%]-->
<KeyPosition
app:framePosition="85"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.5" />
<!-- ImageView的轨迹位置 整个运动的[80%,90%]-->
<KeyPosition
app:framePosition="90"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView"
app:pathMotionArc="none"
app:percentX="0.5"
app:percentY="0.8" />
</KeyFrameSet>
</Transition>
</MotionScene>
二.KeyFrmeSet实现类似贝塞尔曲线动画
1.效果图
2.布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/activity_main_constraintlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<androidx.constraintlayout.motion.widget.MotionLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_constraint_layout_scene"
app:motionDebug="SHOW_PATH">
<ImageView
android:id="@+id/imageView1"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/football" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/football" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/football" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/football" />
<ImageView
android:id="@+id/imageView5"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/football" />
</androidx.constraintlayout.motion.widget.MotionLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
3.描述文件
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 开始ConstraintSet集合 -->
<ConstraintSet android:id="@+id/start">
<!-- 开始位置 ImageView1 屏幕左上角 -->
<Constraint
android:id="@id/imageView1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 开始位置 ImageView2 屏幕左上角 与上一个ImageView重叠 -->
<Constraint
android:id="@id/imageView2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 开始位置 ImageView3 屏幕左上角 与上一个ImageView重叠 -->
<Constraint
android:id="@id/imageView3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 开始位置 ImageView4 屏幕左上角 与上一个ImageView重叠 -->
<Constraint
android:id="@id/imageView4"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 开始位置 ImageView5 屏幕左上角 与上一个ImageView重叠 -->
<Constraint
android:id="@id/imageView5"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<!-- 结束ConstraintSet集合 -->
<ConstraintSet android:id="@+id/end">
<!-- 结束位置 ImageView1 屏幕底部布局左边位置 -->
<Constraint
android:id="@id/imageView1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<!-- 结束位置 ImageView2 屏幕底部 ImageView1和ImageView3中间位置 -->
<Constraint
android:id="@id/imageView2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/imageView1"
app:layout_constraintRight_toLeftOf="@id/imageView3" />
<!-- 结束位置 ImageView3 屏幕底部中间位置 -->
<Constraint
android:id="@id/imageView3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<!-- 结束位置 ImageView4 屏幕底部 ImageView3和ImageView5中间位置 -->
<Constraint
android:id="@id/imageView4"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/imageView3"
app:layout_constraintRight_toLeftOf="@id/imageView5" />
<!-- 结束位置 ImageView5 屏幕底部布局右边位置 -->
<Constraint
android:id="@id/imageView5"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</ConstraintSet>
<!-- 动画轨迹 指定开始&结束的ConstraintSet 以及动画持续的时间-->
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@id/start"
app:duration="3000">
<!-- 动画开始的方式是 点击 ImageView1 -->
<OnClick
app:clickAction="toggle"
app:targetId="@id/imageView1" />
<!-- KeyFrameSet集合 -->
<KeyFrameSet>
<!-- ImageView1的轨迹位置 整个运动的[0%,20%]-->
<KeyPosition
app:framePosition="20"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView1"
app:percentX="0.68"
app:percentY="0.3" />
<!-- ImageView1的轨迹位置 整个运动的[20%,38%]-->
<KeyPosition
app:framePosition="38"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView1"
app:pathMotionArc="startVertical"
app:percentX="0.9"
app:percentY="0.65" />
<!-- ImageView1的轨迹位置 整个运动的[38%,46%]-->
<KeyPosition
app:framePosition="46"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView1"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView1的轨迹位置 整个运动的[46%,65%]-->
<KeyPosition
app:framePosition="65"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView1"
app:pathMotionArc="startVertical"
app:percentX="0.1"
app:percentY="0.62" />
<!-- ImageView1的轨迹位置 整个运动的[65%,80%]-->
<KeyPosition
app:framePosition="80"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView1"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.5" />
<!-- ImageView1的轨迹位置 整个运动的[80%,90%]-->
<KeyPosition
app:framePosition="90"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView1"
app:pathMotionArc="none"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView2的轨迹位置 整个运动的[0%,20%]-->
<KeyPosition
app:framePosition="20"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView2"
app:percentX="0.68"
app:percentY="0.3" />
<!-- ImageView2的轨迹位置 整个运动的[20%,40%]-->
<KeyPosition
app:framePosition="40"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView2"
app:pathMotionArc="startVertical"
app:percentX="0.9"
app:percentY="0.65" />
<!-- ImageView2的轨迹位置 整个运动的[40%,50%]-->
<KeyPosition
app:framePosition="50"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView2"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView2的轨迹位置 整个运动的[50%,60%]-->
<KeyPosition
app:framePosition="60"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView2"
app:pathMotionArc="startVertical"
app:percentX="0.1"
app:percentY="0.62" />
<!-- ImageView2的轨迹位置 整个运动的[60%,80%]-->
<KeyPosition
app:framePosition="80"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView2"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.5" />
<!-- ImageView2的轨迹位置 整个运动的[80%,90%]-->
<KeyPosition
app:framePosition="90"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView2"
app:pathMotionArc="none"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView3的轨迹位置 整个运动的[0%,25%]-->
<KeyPosition
app:framePosition="25"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView3"
app:percentX="0.68"
app:percentY="0.3" />
<!-- ImageView3的轨迹位置 整个运动的[25%,45%]-->
<KeyPosition
app:framePosition="45"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView3"
app:pathMotionArc="startVertical"
app:percentX="0.9"
app:percentY="0.65" />
<!-- ImageView3的轨迹位置 整个运动的[45%,52%]-->
<KeyPosition
app:framePosition="52"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView3"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView3的轨迹位置 整个运动的[52%,66%]-->
<KeyPosition
app:framePosition="66"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView3"
app:pathMotionArc="startVertical"
app:percentX="0.1"
app:percentY="0.62" />
<!-- ImageView3的轨迹位置 整个运动的[66%,85%]-->
<KeyPosition
app:framePosition="85"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView3"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.5" />
<!-- ImageView3的轨迹位置 整个运动的[85%,92%]-->
<KeyPosition
app:framePosition="92"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView3"
app:pathMotionArc="none"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView4的轨迹位置 整个运动的[0%,25%]-->
<KeyPosition
app:framePosition="25"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView4"
app:percentX="0.68"
app:percentY="0.3" />
<!-- ImageView4的轨迹位置 整个运动的[25%,48%]-->
<KeyPosition
app:framePosition="48"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView4"
app:pathMotionArc="startVertical"
app:percentX="0.9"
app:percentY="0.65" />
<!-- ImageView4的轨迹位置 整个运动的[48%,55%]-->
<KeyPosition
app:framePosition="55"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView4"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView4的轨迹位置 整个运动的[55%,69%]-->
<KeyPosition
app:framePosition="69"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView4"
app:pathMotionArc="flip"
app:percentX="0.1"
app:percentY="0.62" />
<!-- ImageView4的轨迹位置 整个运动的[69%,89%]-->
<KeyPosition
app:framePosition="89"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView4"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.5" />
<!-- ImageView4的轨迹位置 整个运动的[89%,94%]-->
<KeyPosition
app:framePosition="94"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView4"
app:pathMotionArc="none"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView5的轨迹位置 整个运动的[0%,30%]-->
<KeyPosition
app:framePosition="30"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView5"
app:percentX="0.68"
app:percentY="0.3" />
<!-- ImageView5的轨迹位置 整个运动的[30%,51%]-->
<KeyPosition
app:framePosition="51"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView5"
app:pathMotionArc="startVertical"
app:percentX="0.9"
app:percentY="0.65" />
<!-- ImageView5的轨迹位置 整个运动的[51%,56%]-->
<KeyPosition
app:framePosition="56"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView5"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.8" />
<!-- ImageView5的轨迹位置 整个运动的[56%,73%]-->
<KeyPosition
app:framePosition="73"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView5"
app:pathMotionArc="flip"
app:percentX="0.1"
app:percentY="0.62" />
<!-- ImageView5的轨迹位置 整个运动的[73%,94%]-->
<KeyPosition
app:framePosition="94"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView5"
app:pathMotionArc="startVertical"
app:percentX="0.5"
app:percentY="0.5" />
<!-- ImageView5的轨迹位置 整个运动的[94%,97%]-->
<KeyPosition
app:framePosition="97"
app:keyPositionType="parentRelative"
app:motionTarget="@id/imageView5"
app:pathMotionArc="none"
app:percentX="0.5"
app:percentY="0.8" />
</KeyFrameSet>
</Transition>
</MotionScene>