【Android】MotionLayout实现动画

MotionLayout不断地更新,文章并不适用全部最近的更新内容。

引入

MotionLayout是Android支持库中的一个布局容器,它可以帮助实现复杂的界面动画和过渡效果。MotionLayout结合了ConstraintLayout和MotionScene的功能,可以通过定义关键帧和过渡效果来创建各种复杂的动画效果。

ConstraintSet

  1. 创建和应用约束关系:

    • ConstraintSet constraintSet = new ConstraintSet(): 创建一个新的ConstraintSet对象。
    • constraintSet.clone(ConstraintLayout layout): 从一个ConstraintLayout中克隆约束关系到ConstraintSet对象中。
    • constraintSet.applyTo(ConstraintLayout layout): 将ConstraintSet对象中的约束关系应用到指定的ConstraintLayout中。
  2. 添加和修改约束关系:

    • constraintSet.connect(int startID, int startSide, int endID, int endSide, int margin): 添加两个视图之间的连接关系,并指定连接的边和边距。
    • constraintSet.setHorizontalBias(int viewId, float bias): 设置视图在水平方向上的偏移位置。
    • constraintSet.setVerticalBias(int viewId, float bias): 设置视图在垂直方向上的偏移位置。
    • constraintSet.constrainHeight(int viewId, int height): 设置视图的高度。
    • constraintSet.constrainWidth(int viewId, int width): 设置视图的宽度。
    • constraintSet.setVisibility(int viewId, int visibility): 设置视图的可见性。
  3. 移除约束关系:

    • constraintSet.clear(int viewId): 移除指定视图的所有约束关系。
    • constraintSet.clear(int viewId, int anchor): 移除指定视图与指定锚点视图之间的约束关系。

我们可以使用 ConstraintSet 和 TransitionManager 来实现一个平移动画。

TransitionManager和MotionLayout有什么区别?

ransitionManager和MotionLayout是Android中用于实现动画效果的两个不同的类。

TransitionManager是Android提供的一个类,用于管理场景之间的转换和动画效果。它可以在不同的ViewGroup之间实现平滑的过渡动画,例如在切换布局、添加或移除View时的过渡效果。TransitionManager通过场景(Scene)的概念来管理动画,可以定义多个不同的场景,并在场景之间进行转换。

MotionLayout是一个继承自ConstraintLayout的布局容器,它可以用来实现复杂的动画和过渡效果。MotionLayout基于ConstraintSet和Transition的概念,通过定义起始和结束状态的约束集合(ConstraintSet),再结合过渡效果(Transition)来实现布局的动画过渡。与TransitionManager相比,MotionLayout提供了更强大和灵活的动画控制能力,可以实现更复杂的动画效果,例如更精细的属性动画、路径动画、关键帧动画等。

当需要简单的场景过渡效果,例如在切换布局或添加/移除View时的平滑过渡,可以使用TransitionManager。而当需要实现更复杂、精细的动画效果时,例如属性动画、路径动画等,可以选择使用MotionLayout。 MotionLayout相对于TransitionManager来说功能更加强大,但也更复杂一些,需要更多的配置和设置。因此,根据具体需求和复杂度来选择使用哪个类。

使用

在MotionLayout布局下每个控件都需要设置一个id

在xml根布局改成MotionLayout后,爆红,可利用编译器自动生成xml文件用来对应layoutDescription属性。该文件用来定义这个动画的动画过程和约束条件。

layoutDescription="@xml/fragment_motion_01_basic_scene"

打开该生成文件:

image-20231107002332889

可以看到本质是MotionScene+ Transition,用于描述动画的动效。

  • ConstrainSet描述了开始或结束时页面控件的状态
  • Transtion指定了动画要使用的ConstrainSet,动画的触发方式等。

编译器已经自动生成了Start和End的ConstrainSet,那我们主要工作就是操作MotionScene+ Transition

ConstrainSet(属性类似于ConstrainLayout)

ConstraintSet是Android中的一个工具类,它用于在代码中动态设置和管理ConstraintLayout的约束关系。ConstraintLayout是一个强大的布局容器,可以实现复杂的界面布局,而ConstraintSet可以帮助我们在运行时修改和更新这些布局。

使用ConstraintSet,我们可以在不重新加载布局文件的情况下,通过代码来添加、修改或移除视图的约束关系,实现动态的布局效果。下面是一些ConstraintSet的常用方法和功能:

ConstrainSet下的标签类似于Constrainlayout的属性,我们可以直接内嵌Constrain,直接描述出Start和end的状态,再通过Transition进行动画效果的配置。

<?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 android:id="@+id/start">
        <Constraint android:id="@+id/button"
            android:background="@color/orange"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"  />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint  android:id="@+id/button"
            android:background="@color/orange"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <Transition
         ...
    </Transition>
</MotionScene>

Transition

属性

  1. app:constraintSetStart:指定过渡的起始状态的ConstraintSet。可以使用@id引用已定义的ConstraintSet。
  2. app:constraintSetEnd:指定过渡的结束状态的ConstraintSet。同样也可以使用@id引用已定义的ConstraintSet。
  3. app:duration:指定动画过渡的持续时间,单位为毫秒。
  4. app:staggered:在多个View之间应用过渡效果时,指定是否应该依次进行过渡。可以设置为truefalse
  5. app:autoTransition:指定是否在布局文件加载时自动开始过渡动画。可以设置为startToEndendToStartautoTransition
  6. app:cycleDuration:指定循环过渡的总时间。当使用循环过渡时,可以设置循环的总时间。
  7. app:transitionOnBackward:指定当用户反向滑动时是否触发过渡动画。可以设置为normaljumpToEndjumpToStart
  8. app:transitionDisable:指定是否禁用过渡动画。可以设置为truefalse
  9. app:motionInterpolator:指定过渡动画的插值器。可以设置为linearacceleratedeceleratefast_out_linear_infast_out_slow_in等。
  10. app:pathMotionArc:指定过渡动画中路径的弧度。可以设置为nonestartVerticalendVerticalstartHorizontalendHorizontal等。
  11. app:touchAnchorId:指定触摸点的锚点View的ID。在触摸事件中,可以定义触摸点锚定的位置。

定义的可处理事件有以下三种,用来规定用户交互逻辑详细法则。

image-20231107005524702

OnClick

在Transition中,可以定义OnClick标签用于处理用户点击事件,

        <OnClick
            motion:clickAction="toggle"
            motion:targetId="@+id/button" />
        <!--OnClick 用于处理用户点击事件 -->
        <!--targetId 设置触发点击事件的组件 -->
        <!--clickAction 设置点击操作的响应行为,这里是使动画过渡到结束状态 -->
  1. app:clickAction="toggle":点击时切换到指定的ConstraintSet。

    例如,app:clickAction="@id/secondConstraintSet"表示点击时切换到ID为secondConstraintSet的ConstraintSet。

  2. app:clickAction="jumpToEnd":点击时立即跳转到Transition的结束状态。

  3. app:clickAction="jumpToStart":点击时立即跳转到Transition的开始状态。

  4. app:clickAction="none":点击时不执行任何操作,保持当前状态不变。

  5. app:clickAction="transitionToEnd":点击时执行Transition到结束状态的动画。

  6. app:clickAction="transitionToStart":点击时执行Transition到开始状态的动画。

  7. app:clickAction="transitionWithCrossfade":点击时执行Transition到指定ConstraintSet的动画,并添加淡入淡出效果。

OnSwipe

OnSwipe一般用于处理拖拽事件,其中有一个弹簧的理念。

  • dragThreshold:定义拖拽的最小阈值,当拖拽距离小于该值时,视图不会响应拖拽事件。这个属性可以用于控制视图响应拖拽事件的灵敏度。
  • autoCompleteMode:定义自动完成的模式,可以有以下两种取值:
    • continuousVelocity:使用连续的速度自动完成。
    • spring:使用弹簧效果自动完成。
  • maxVelocity:定义最大速度,当拖拽速度超过该值时,视图将不再响应拖拽事件。
  • maxAcceleration:定义最大加速度,当拖拽加速度超过该值时,视图将不再响应拖拽事件。
  • springMass:定义弹簧质量。
  • springStiffness:定义弹簧刚度。
  • springDamping:定义弹簧阻尼。
  • springStopThreshold:定义弹簧停止的阈值,当速度小于该值时,弹簧将停止弹动。
  • springBoundary:定义弹簧边界,可以有以下几种取值:
    • overshoot:超出边界时弹簧会继续弹动。
    • bounceStart:当拖拽到开始位置时弹簧会弹动。
    • bounceEnd:当拖拽到结束位置时弹簧会弹动。
    • bounceBoth:当拖拽到开始或结束位置时弹簧会弹动。
  • dragDirection:定义拖拽方向,可以有以下几种取值:
    • horizontal:只能水平拖拽。
    • vertical:只能垂直拖拽。
    • both:可以水平和垂直拖拽。
  • touchAnchorId:定义触摸点的锚定视图 ID。
  • touchAnchorSide:定义触摸点在锚定视图中的位置,可以有以下几种取值:
    • top:触摸点位于锚定视图的顶部。
    • bottom:触摸点位于锚定视图的底部。
    • left:触摸点位于锚定视图的左侧。
    • right:触摸点位于锚定视图的右侧。
    • center:触摸点位于锚定视图的中心。
  • rotationCenterId:定义旋转中心的视图 ID。
  • touchRegionId:定义触摸区域的视图 ID。
  • limitBoundsTo:定义限制边界的视图 ID。
  • nestedScrollFlags:定义嵌套滚动的标志位,可以有以下几种取值:
    • none:不支持嵌套滚动。
    • disablePostScroll:禁止滚动结束后的滚动。
    • disableScroll:禁止滚动。
    • supportScrollUp:支持向上滚动。
  • moveWhenScrollAtTop:定义是否在滚动到顶部时允许拖拽。
  • onTouchUp:定义当手指离开屏幕时的行为,可以有以下几种取值:
    • autoComplete:自动完成拖拽。
    • autoCompleteToStart:自动完成拖拽并回到开始位置。
    • autoCompleteToEnd:自动完成拖拽并回到结束位置。
    • stop:停止拖拽。
    • decelerate:减速拖拽。
    • decelerateAndComplete:减速拖拽并完成拖拽。
    • neverCompleteToStart:永远不要自动完成到开始位置。
    • neverCompleteToEnd:永远不要自动完成到结束位置。

KeyFrameSet

KeyFrameSet(关键帧集合)是在动画中定义和控制关键帧的一种方式。通过使用KeyFrameSet,可以定义动画的起始和结束状态控制动画的过程和插值方式实现多阶段动画
在这里插入图片描述

需要定义一个 KeyPosition 对象和一个 KeyAttribute 对象。

KeyPosition 对象定义了中间状态的位置,KeyAttribute 对象定义了中间状态的属性值。您可以将多个 KeyPositionKeyAttribute 对象组合成一个 Keyframes 对象,并将其应用于约束布局中的任何属性

KeyPosition
<KeyPosition
    time="1000"               // 时间点,单位为毫秒
    position="0, 0, 0"        // 位置坐标,可以是二维或三维坐标
    interpolation="linear"    // 插值方式,例如线性插值
    easing="ease-in-out"      // 缓动效果,例如渐入渐出
/>
  • keyPositionType:定义如何计算关键帧的偏差。可以设置为 deltaRelativepathRelativeparentRelative 三种取值之一。使用 deltaRelative 时,关键帧的偏差相对于线性路径计算;使用 pathRelative 时,关键帧的偏差相对于路径计算;使用 parentRelative 时,关键帧的偏差相对于父视图计算。
  • percentXpercentY:定义关键帧在 X 和 Y 轴上的位置。可以设置为 0 到 1 之间的浮点数,表示从开始状态到结束状态之间的相对位置。
  • percentWidthpercentHeight:定义宽度和高度的变化量。可以设置为 0 到 1 之间的浮点数,表示从开始状态到结束状态之间的相对变化量。注意,如果宽度或高度没有变化,则这些属性将没有任何效果。
  • framePosition:定义关键帧在动画中的位置。可以设置为 0 到 100 之间的整数,表示从动画开始到结束之间的相对位置。
  • motionTarget:定义应用此关键帧的运动目标。可以是一个视图或者一个运动场景。
  • transitionEasing:定义关键帧的过渡缓动效果。可以使用 Android 系统中提供的各种缓动函数,比如 easeIn, easeOut 等。
  • pathMotionArc:定义关键帧在路径上的运动方式。可以设置为 nonestartVerticalendVerticalfliprotate 等五种取值之一。
  • curveFit:定义关键帧的插值方式。可以设置为 linearsplinediscrete 等三种取值之一。
  • drawPath:定义是否在编辑器中绘制关键帧路径。
  • sizePercent:定义宽度和高度的百分比。可以设置为 0 到 1 之间的浮点数,表示相对于视图父级的百分比。
KeyAttribute

framePosition:定义关键帧在动画中的位置。可以设置为 0 到 100 之间的整数,表示从动画开始到结束之间的相对位置。

motionTarget:定义应用此关键帧的运动目标。可以是一个视图或者一个运动场景。

transitionEasing:定义关键帧的过渡缓动效果。可以使用 Android 系统中提供的各种缓动函数,比如 easeIn, easeOut 等。

curveFit:定义关键帧的插值方式。可以设置为 linearsplinediscrete 等三种取值之一。

motionProgress:定义关键帧的运动进度,即从开始状态到结束状态之间的进度百分比。

alpha:定义视图的不透明度。可以设置为 0 到 1 之间的浮点数,表示视图的透明度。

elevation:定义视图的高度。可以设置为一个浮点数,表示视图的高度。

rotationrotationXrotationY:定义视图的旋转角度,可以分别设置 X、Y、Z 轴上的旋转角度。

transformPivotXtransformPivotY:定义视图的变换中心点坐标。

transformPivotTarget:定义变换中心点的目标视图。

transitionPathRotate:定义视图在路径上的旋转角度。

scaleXscaleY:定义视图的缩放比例。

translationXtranslationYtranslationZ:定义视图的位置偏移量。

CustomAttribute

CustomAttribute是一种用于自定义属性的元素。它允许你在布局文件中定义和使用自定义属性,以便在MotionScene中使用这些属性来控制动画效果。你可以在MotionLayout中设置一个起始状态和一个结束状态,然后使用CustomAttribute来设置自定义属性在这两个状态之间的过渡效果。

<CustomAttribute
    app:attributeName="customProperty"  // 自定义属性的名称
    app:customDimension="100dp"         // 自定义属性的值
    />
属性
  1. app:attributeName: 定义自定义属性的名称。
  2. app:customColorValue: 设置自定义属性的颜色值,例如#FF0000表示红色。
  3. app:customDimension: 设置自定义属性的尺寸值,例如100dp表示100个设备独立像素。
  4. app:customFloatValue: 设置自定义属性的浮点数值。
  5. app:customIntValue: 设置自定义属性的整数值。
  6. app:customStringValue: 设置自定义属性的字符串值。

自定义属性的名称必须与View具有相应的setter方法名称相匹配,才能在MotionLayout中使用。例如,如果您想要定义一个名为"customText"的CustomAttribute来控制TextView的文本内容,那么TextView中需要有一个名为为"setCustomText"的方法,以便MotionLayout能够找到相应的setter方法。

  • 37
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 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
发出的红包

打赏作者

xoliu1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值