MotionLayout使用KeyFrameSet实现曲线动画(上)

一.重点属性讲解

1.KeyFrameSet

作用:指定运动序列过程中视图的位置和属性。默认情况下,运动会从初始状态逐渐进入结束状态。可以构建更复杂的运动。

KeyFrameSet 包含 <KeyPosition> 或 <KeyAttribute> 节点。这些节点中的每个节点都指定目标视图在运动特定点处的位置或属性。

2.KeyPosition

作用:指定视图在运动序列中特定时刻的位置。该属性用于调整默认的运动路径。包含于<KeyFrameSet>。

属性

<1> motion:motionTarget:被控制视图的Id。

<2> motion:framePosition:[1-99] 之间的整数。用于指定运动序列中视图何时到达此 <KeyPosition> 指定的点。例如,如果 framePosition 为 25,则视图在整个运动路径的四分之一处到达指定点。

<3> motion:percentX&motion:percentY:是相对于父视图指定的。X 为横轴,范围从 0(左端)到 1(右端)。Y 为纵轴,其中 0 为顶部,1 为底部。

<4> motion:keyPositionType:指定如何解释 percentX 和 percentY 值。
       

 可能的设置包括:

[1] parentRelative:percentX 和 percentY 是相对于父视图指定的。X 为横轴,范围从 0(左端)到 1(右端)。Y 为纵轴,其中 0 为顶部,1 为底部。

例如,如果您希望目标视图到达父视图右端中间的某个点,可以将 percentX 设置为 1,将 percentY 设置为 0.5。

[2] deltaRelative:percentX 和 percentY 是相对于视图在整个运动序列过程中移动的距离指定的。X 为横轴,Y 为纵轴;在这两种情况下,0 为视图在该轴上的起始位置,1 为最终位置。

例如,假设目标视图向上移动 100 dp,然后再向右移动 100 dp,但是您希望视图按以下方式移动:首先在运动的前四分之一部分向上移动 40 dp,然后向上呈弧形移动。为此,请将 framePosition 设置为 25,将 keyPositionType 设置为 deltaRelative,并将 percentY 设置为 -0.4。

[3] pathRelative:X 轴是目标视图在路径范围内移动的方向,其中 0 为起始位置,1 为最终位置。Y 轴垂直于 X 轴,正值位于路径左侧,负值位于右侧;设置一个非零的 percentY 可使视图向一个方向或另一个方向呈弧形运动。因此,视图的初始位置为 (0,0),最终位置为 (1,0)。

例如,假设您希望视图按如下方式移动:在运动序列前半部分的移动距离占总距离的 10%,然后加速移动以覆盖剩余 90% 的距离。为此,请将 framePosition 设置为 50,将 keyPositionType 设置为 pathRelative,并将 percentX 设置为 0.1。

3.KeyAttribute

作用:指定视图在运动序列中特定时刻的属性。可以使用 <KeyAttribute> 设置视图的任何标准属性。

例如,假设视图的不透明度 (android:alpha) 在初始 <ConstraintSet> 中设为 0,在最终 <ConstraintSet> 中设为 1。默认情况下,这会导致视图在整个运动序列上以线性方式淡入。如果您希望视图直至运动序列 80% 处都保持不可见,然后快速淡入,请添加单个 <KeyAttribute> 节点,将 motion:framePosition 设为 80 并将 android:alpha 设为 0。

属性

<1> motion:motionTarget:被控制视图的Id。

<2> motion:framePosition:从 1 到 99 之间的整数,用于指定在运动序列中视图何时具有该 <KeyAttribute> 指定的属性。例如,如果 framePosition 为 25,则视图在运动的四分之一处具有指定属性。

具体哪些属性

二.KeyFrameSet基础使用

1.布局文件

<?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/imageView"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@color/colorPrimaryDark" />

    </androidx.constraintlayout.motion.widget.MotionLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

2.描述文件

<?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="50dp"
            android:layout_height="50dp"
            android:layout_marginLeft="20dp"
            android:layout_marginBottom="20dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent" />

    </ConstraintSet>

    <!-- 结束ConstraintSet集合 -->
    <ConstraintSet android:id="@+id/end">

        <!-- 结束ImageView位置 右下角 -->
        <Constraint
            android:id="@id/imageView"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginRight="20dp"
            android:layout_marginBottom="20dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent" />

    </ConstraintSet>

    <!-- Transition 轨迹 -->
    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@id/start">

        <!-- KeyFrameSet集合  -->
        <KeyFrameSet>

            <!-- KeyPosition确定运动过程中的位置 具体值讲解如上 -->
            <KeyPosition
                app:framePosition="50"
                app:keyPositionType="parentRelative"
                app:motionTarget="@id/imageView"
                app:percentY="0.5" />

            <!-- KeyAttribute确定运动过程中的属性 具体值讲解如上 -->
            <KeyAttribute
                android:rotation="-360"
                android:scaleX="2.0"
                android:scaleY="2.0"
                app:framePosition="50"
                app:motionTarget="@id/imageView" />

            <!-- KeyAttribute确定运动过程中的属性 具体值讲解如上 -->
            <KeyAttribute
                android:rotation="-720"
                android:scaleX="1.0"
                android:scaleY="1.0"
                app:framePosition="100"
                app:motionTarget="@id/imageView" />

        </KeyFrameSet>

        <OnSwipe
            app:dragDirection="dragRight"
            app:touchAnchorId="@id/imageView"
            app:touchAnchorSide="bottom" />

    </Transition>

</MotionScene>

3.结果

4.属性说明
<1> KeyPosition
<KeyPosition
    app:framePosition="50"
    app:keyPositionType="parentRelative"
    app:motionTarget="@id/imageView"
    app:percentY="0.5" />
app:framePosition="50"  移动的前半部分50%


app:keyPositionType="parentRelative"  app:percentX&app:percentY 相对于父视图指定


app:motionTarget="@id/imageView"  受控制的View的Id


app:percentY="0.5"  Y 为纵轴,Y的中间位置是移动的中间位置。

<2> KeyAttribute 移动的前半部分50%

<KeyAttribute
    android:rotation="-360"
    android:scaleX="2.0"
    android:scaleY="2.0"
    app:framePosition="50"
    app:motionTarget="@id/imageView" />
app:motionTarget="@id/imageView" 受控制的View的Id


app:framePosition="50"  运动的二分之一处具有指定属性


android:rotation="-360" 普通View的属性 逆时针旋转一周
android:scaleX="2.0"    普通View的属性 X轴变大一倍
android:scaleY="2.0"    普通View的属性 Y轴变大一倍

<3> KeyAttribute 移动的后半部分50%

<KeyAttribute
    android:rotation="-720"
    android:scaleX="1.0"
    android:scaleY="1.0"
    app:framePosition="100"
    app:motionTarget="@id/imageView" />
app:motionTarget="@id/imageView" 受控制的View的Id


app:framePosition="100"  运动的最后处具有指定属性


android:rotation="-720" 普通View的属性 逆时针旋转两周
android:scaleX="1.0"    普通View的属性 X轴成原来的大小
android:scaleY="1.0"    普通View的属性 Y轴成原来的大小

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 Android MotionLayout 使用示例: 1. 在 XML 布局文件中添加 MotionLayout: ```xml <android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/motion_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_main"> <!-- 添加子视图 --> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </android.support.constraint.motion.MotionLayout> ``` 2. 在 res/xml 目录下创建 MotionScene 文件 scene_main.xml,定义 MotionLayout动画场景: ```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/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:layout_marginStart="16dp" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <!-- 定义结束状态 --> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" /> </ConstraintSet> <!-- 定义转换过程 --> <Transition motion:constraintSetEnd="@id/end" motion:constraintSetStart="@id/start"> <OnSwipe motion:dragDirection="dragDown" motion:touchAnchorId="@id/text_view" motion:touchAnchorSide="top" /> </Transition> </MotionScene> ``` 3. 在 Activity 或 Fragment 中获取 MotionLayout,并启动动画: ```java MotionLayout motionLayout = findViewById(R.id.motion_layout); motionLayout.transitionToEnd(); ``` 这是一个简单的 Android MotionLayout 使用示例,你可以根据自己的需要进行更复杂的场景和动画定义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值