《译文》MotionLayout系列-4

MotionLayout动画系统通过插入两个状态之间的值(通常是小部件的位置/大小)来工作,这两个状态使用ConstraintLayout的完整约束系统以及视图属性指定。这两种状态之间的转换也可以完全由触摸驱动。该系统通常会为您的过渡提供出色的结果。
除了状态之外,MotionLayout还支持关键帧 - 在本系列的第二部分中简要介绍- 我们将在本文中深入介绍。请注意,虽然关键帧很棒,但它绝对是一个更专业的工具; 你可能不需要的,或者只是偶尔需要的。

请记住,在应用程序中添加动作应该是有意义的; 不要过度!

但是,如果您需要额外的功能来定义转换,关键帧将扩展您可以使用MotionLayout执行的操作。正如您将看到的,有很多要涵盖的内容:

  • 关键帧
  • 位置关键帧
  • Arc Motion
  • 缓解
  • 属性关键帧
  • 循环关键帧和TimeCycle关键帧(我们将在第V部分介绍)

关键帧:时间中的Rendez-vous

在较高级别,关键帧允许您在两个状态之间的插值期间的给定时间指定更改。
keyframe
MotionLayout支持不同类型的关键帧:

  • 位置关键帧: KeyPosition
  • 属性关键帧: KeyAttribute
  • 循环关键帧: KeyCycle
  • TimeCycle关键帧: KeyTimeCycle

请注意,每种类型的关键帧都独立于其他关键帧 - 也就是说,您不需要在同一点定义所有关键帧(但是您不能在同一点定义相同类型的多个关键帧)

共同属性

所有关键帧(Position,Attribute,Cycle,TimeCycle)都有一些共同的属性:

  • motion:framePosition :何时在过渡期间应用关键帧(从0到100)
  • motion:target :该关键帧会影响哪个对象
  • motion:transitionEasing :使用哪条缓动曲线(默认为线性)
  • motion:curveFit:样条曲线(默认)或线性 - 插值曲线适合关键帧。默认值是单调样条曲线,使转换更平滑,但您可以决定使用线性段。

位置关键帧

位置关键帧可能是您将遇到或使用的最常见的关键帧。它们允许您在过渡期间修改窗口小部件在屏幕上的路径。例如,让我们采用MotionLayout(“父”)中包含的单个小部件的以下动画:

keyposition

我们有一个开始(左下)和结束(右上)状态,运动路径只是这两个状态之间的线性插值 - 小部件将以直线移动。

keyposition-start-end
通过引入位置关键帧,我们可以将运动路径更改为弯曲运动:
keyframe
keyframe result
添加更多关键帧将允许您创建复杂的运动路径。
compose keyframe

<KeyFrameSet>
    <KeyPosition
        motion:keyPositionType="pathRelative"
        motion:percentX="0.75"
        motion:percentY="-0.3"
        motion:framePosition="25"
        motion:target="@id/button"/>
    <KeyPosition
        motion:keyPositionType="pathRelative"
        motion:percentY="-0.4"
        motion:framePosition="50"
        motion:target="@id/button"/>
    <KeyPosition
        motion:keyPositionType="pathRelative"
        motion:percentX="0.25"
        motion:percentY="-0.3"
        motion:framePosition="75"
        motion:target="@id/button"/>
</KeyFrameSet>

为什么定位关键帧?

如果ConstraintSets已经允许您以非常灵活的方式定位窗口小部件,您可能会问自己,位置关键帧的重点是什么。有几个原因:

  • 关键帧表示瞬态修改,而ConstraintSets表示“休息”状态
  • 关键帧比ConstraintSet更轻量级
  • 位置关键帧允许您操纵窗口小部件的运动路径 - 相反,ConstraintSets指定窗口小部件相对于其他窗口小部件的位置。

注意:可以在MotionScene中定义多个ConstraintSet,因此如果您有多步运动,其中这些步骤是有效的“静止”状态,则可以使用它们而不是关键帧。将状态转换为状态必须在代码中完成(更改侦听器可用)。

XML表示

关键帧包含在<KeyFrameSet>属性中,该属性本身包含在<Transition>MotionScene文件中。位置关键帧通过标记表示<KeyPosition>,并且至少需要包含:

  • target:关键帧适用的小部件
  • framePosition:从0到100,关键帧何时适用
  • keyPositionType:使用的坐标系, parentRelative, deltaRelative, pathRelative
  • percentX / percentY :位置的(x,y)坐标
<Transition ...>
    <KeyFrameSet>
        <KeyPosition
            motion:keyPositionType="parentRelative"
            motion:percentY="0.25"
            motion:framePosition="50"
            motion:target="@+id/button"/>
    </KeyFrameSet>
</Transition>

不同的坐标系

MotionLayout中的开始和结束状态允许复杂的定位。作为ConstraintSets,他们可以访问ConstraintLayout的全部功能。系统将正确处理这些状态的密度,屏幕方向,语言等的变化。
对于在这样的系统中有用的位置关键帧,我们需要它们能够以类似的自适应方式定位自己 - 我们不能简单地将它们定义为固定位置。
为了解决这个问题,同时保持关键帧系统的轻量级,我们提出了一种灵活的方法 - 每个关键帧的位置用给定坐标系中的(x,y)坐标对表示:

  • motion:percentX=””
  • motion:percentY=””

这些坐标的含义取决于所使用的坐标系统的类型:parentRelative,deltaRelative,或pathRelative。

注意:每个关键帧位置都是单独完成的 - 每个关键帧位置都可以使用自己的坐标系表示,与其他坐标系无关。

parentRelative

坐标相对于父容器表示。这是表达关键帧位置的非常简单直观的方式,通常就足够了。您通常会将此用于需要相对于容器的大型运动。
parentrelative

由于此坐标系仅基于父维度,而不是基于移动窗口小部件的开始/结束位置,因此您可能会遇到结果关键帧位置在次优位置(相对于开始/结束位置)结束的情况。

deltaRelative

第二个坐标系通过使用开始/结束位置来定义这个确切的问题。坐标表示起始位置和结束位置之间距离的百分比。
deltaRelative

类似地parentRelative,这是一个相对直观的坐标系,通常也会给出好的结果。当您希望窗口小部件以水平或垂直运动开始或结束时,它尤其有用。
它也存在一个潜在的问题 - 因为它是根据窗口小部件的开始和结束位置之间的差异定义的,如果差异非常小(或为零),关键帧的位置在受影响的轴上不会改变。例如,如果小部件在屏幕上从左向右移动,同时保持相同的高度,则使用deltaRelative percentY位置关键帧将无效。

pathRelative

该最后一个坐标系被定义为相对于起始状态和结束状态之间的直线路径。它确实解决了使用deltaRelative坐标系引起的问题- 即使在不在垂直轴上移动的小部件上,使用pathRelative也可以将位置关键帧设置为偏离路径。请注意,也支持负坐标。它是一个更专业的坐标系,但是在时间上特别有用。一个例子是实现即使端点改变也将保持不变的曲线形状(如“S”)。
pathRelative

Arc Motion

材料设计中使用的典型运动类型是圆弧运动。使用MotionLayout创建弧形运动的一种方法是在开始位置和结束位置之间添加正确放置的位置关键帧,如上一节中所述。
在ConstraintLayout 2.0.0 alpha 2中,我们介绍了一种实现完美弧形运动的新方法 - 它更易于使用。你只需要加上 motion:pathMotionArc 属性到起始ConstraintSet,从默认线性运动切换到圆弧运动。
让我们看一个基本的例子,屏幕右下角的起始状态和屏幕顶部中间的结束状态。添加属性足以生成弧形运动:

motion:pathMotionArc=”startHorizontal”

shuiping
将参数切换为:

motion:pathMotionArc=”startVertical”

将反转弧的起始方向:

chuizhi
您仍然可以使用位置关键帧来构建更复杂的弧形路径。结果如下:
complex
通过在动画的中间添加一个垂直居中在屏幕上的关键帧来实现:

<KeyPosition 
    motion:keyPositionType =“parentRelative” 
    motion:percentY =“0.5” 
    motion:framePosition =“50” 
    motion:target =“@ id / button”/>

通过设置motion:pathMotionArc属性,该场景中的位置关键帧也可用于更改弧的方向。该属性可以是flip(翻转当前弧形方向),none(恢复为线性运动),也可以是显式startHorizontal或startVertical。
smooth complex

<KeyPosition 
    motion:keyPositionType =“parentRelative” 
    motion:pathMotionArc =“flip” 
    motion:percentY =“0.5” 
    motion:framePosition =“50” 
    motion:target =“@ id / button”/>

liner

<KeyPosition
    motion:keyPositionType="parentRelative"
    motion:pathMotionArc="none"
    motion:percentY="0.5"
    motion:framePosition="50"
    motion:target="@id/button"/>

缓解

在前面的部分中,我们介绍了允许您定义运动路径的各种机制。虽然动画不仅仅是采取的路径; 时机至关重要。

由于位置关键帧是及时指定的,因此您可以使用它们来定义窗口小部件移动的速度或速度,具体取决于行进的空间。

但是在单个段内 - 在开始/结束状态之间或关键帧之间 - 时间插值是线性的。
您可以使用motion:transitionEasing属性指定缓动曲线来更改此设置。您可以在ConstraintSets或关键帧上应用此属性,它将继续应用。它可以采用以下值:

  • cubic(float, float , float, float),其中参数是x1,y1,x2,y2,表示从0,0到1,1的立方贝塞尔曲线的控制点
  • 或使用关键字:standard,accelerate,decelerate,其中是预先定义的曲线,类似于材料设计定义。

标准宽松
start
通常用于为非触摸驱动的动画添加角色。它最适用于开始和结束静止的元素。
加速宽松政策

smooth ace
当将元素移出场景时,通常使用加速。
减速宽松
dec
在将元素移动到场景中时通常使用减速。

KeyAttribute

通过属性关键帧,您可以在动画期间指定给定时间点的窗口小部件属性更改 - 换句话说,它们与位置关键帧类似,但是处理属性而不是位置。
keyattribute
可以指定上面的示例KeyAttribute在MotionScene文件中添加以下元素:

<KeyFrameSet>
    <KeyAttribute
        android:scaleX="2"
        android:scaleY="2"
        android:rotation="-45"
        motion:framePosition="50"
        motion:target="@id/button" />
</KeyFrameSet>

至于KeyPosition,我们需要指定framePosition(当关键帧适用时)和target(对象受影响)。

支持的属性

您可以使用现成的属性是视图属性:android:visibility,android:alpha,android:elevation,android:rotation,android:rotationX,android:rotationY,android:scaleX,android:scaleY,android:translationX,android:translationY,android:translationZ
重要提示:根据您为应用程序定位的SDK级别,其中一些属性将不起作用:

  • android:elevation在SDK 21中引入
  • android:translationZ是在SDK 21中引入的

自定义属性

您可以通过添加子<CustomAttribute>元素在ConstraintSets和KeyAttribute元素中声明自定义属性。此元素需要name(attributeName),它是getter / setter的名称(减去set / get前缀),以及要使用以下属性之一指定的插值或应用值:

  • customColorValue :应用颜色值
  • customColorDrawableValue :应用颜色值,包装为drawable
  • customIntegerValue :应用整数值
  • customFloatValue :应用浮点值
  • customStringValue :应用字符串值
  • customDimension :应用维值
  • customBoolean :应用布尔值

例如,这是与上述动画对应的XML:

<ConstraintSet android:id="@+id/start">
    <Constraint
        android:id="@+id/button" ...>
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#D81B60"/>
    </Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
    <Constraint
        android:id="@+id/button" ...>
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#9999FF"/>
    </Constraint>
</ConstraintSet>

结论

本文介绍了MotionLayout中最常用的关键帧和路径规范。我们将在本系列的第五部分讨论KeyCycle和KeyTimeCycle关键帧,这是引入增加扰动的一个非常强大的方式(如波形),以属性(路径或基于时间的),允许各种有趣但可预见的循环效应(反弹,晃动,脉动等)。

文章代码地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值