Android新控件之MotionLayout 关键帧深入学习<九>

MotionLayout 关键帧

MotionLayout 运动布局继承于ConstraintLayout(约束布局) 它的的大体实现是静态处理放在ConstraintSet(约束集合)上,用ConstraintSet控制布局适应不通的屏幕尺寸

在一些特殊的情况下我们需要一个特殊的过度状态,用于处理一些过渡变化,如下图.中间点就是个开始点到结束点的关键点,用于处理开始点到结束点的动画变化以及路径变化

关键帧作用:

可以应用于位置或属性值;它们基本上允许您在过渡期间的某个时间点指定更改。

关键点过度.gif

代码:

<?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/end"
        motion:constraintSetStart="@+id/start"
        motion:duration="1000"
        motion:motionInterpolator="linear">
        <!--  motion:pathMotionArc="startHorizontal"-->
        <!-- motionInterpolator 动画插值器 -->
        <!-- autoCompleteToEnd 自动完成到结尾  autoComplete自动完成 -->
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorId="@+id/button"
            motion:touchAnchorSide="right" />
        <!--parentRelative 相对父布局的路径  相对控件的-->
        <!--percentY 移动的Y位置(百分比+在下 -在上)-->
        <!--percentX 移动的Y位置(百分比+在右边 -在左边)-->
        <!--motionTarget 目标View-->
        <!--framePosition 0=起点100=终点 什么时候关键帧起作用-->
        <KeyFrameSet>
            <KeyPosition
                motion:framePosition="50"
                motion:keyPositionType="pathRelative"
                motion:motionTarget="@id/button"
                motion:percentX="0.5"
                motion:percentY="-0.5" />

            <!-- KeyAttribute 关键帧的属性-->
            <!--   scaleX    scaleY XY 缩放      -->
            <!--   rotation    旋转      -->
            <!--   framePosition    执行到这个区间的百分之80      -->
            <KeyAttribute
                android:rotation="45"
                android:scaleX="2"
                android:scaleY="2"
                motion:framePosition="80"
                motion:motionTarget="@id/button" />

<!--            <KeyPosition-->
<!--                motion:framePosition="60"-->
<!--                motion:keyPositionType="pathRelative"-->
<!--                motion:motionTarget="@id/button"-->
<!--                motion:percentX="0.7"-->
<!--                motion:percentY="-0.8" />-->
        </KeyFrameSet>
    </Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="BackgroundColor"
                motion:customColorValue="#D81B60" />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="BackgroundColor"
                motion:customColorValue="#9999FF" />
        </Constraint>
    </ConstraintSet>

</MotionScene>

2.关键帧类型

MotionLayout 动画系统通过在使用 ConstraintLayout 的完整约束系统以及视图属性指定的两个状态之间插入值(通常是小部件的位置/大小)来工作。这两种状态之间的转换也可以完全由触摸驱动。这个系统通常会给你的过渡带来很好的效果。


说明

MotionLayout 支持不同类型的关键帧:

  • A: 位置关键帧: KeyPosition
  • B: 属性关键帧: KeyAttribute
  • C: 循环关键帧: KeyCycle
  • D: 时间周期关键帧: KeyTimeCycle

注意:

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

关键帧的通用属性

motion:framePosition : 过渡期间何时应用关键帧(从 0 到 100,位于父布局的100份比例换算)
motion:target : 哪个对象受此关键帧影响(作用与那个控件)
motion:transitionEasing : 使用哪个缓动曲线(默认为线性,移动轨迹曲线路径)
motion:curveFit:样条曲线(默认)或线性——哪条插值曲线适合关键帧。默认为单调样条曲线,使过渡更平滑,但您可以决定改为使用线性段。(我理解为是移动的插值器)

A: KeyPosition 位置关键帧

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


parentRelative.gif

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


parentRelative.png

通过引入位置关键帧,我们可以将运动路径更改为曲线运动:

parentRelative2.gif
parentRelative2.png

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

target: 关键帧应用到的小部件
framePosition: 从 0 到 100,关键帧什么时候应用
keyPositionType:使用的坐标系, parentRelative, deltaRelative, pathRelative
percentX / percentY : 位置的 (x,y) 坐标
pathMotionArc 圆弧运动
transitionEasing 缓和过度

代码

<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>

属性说明

1.定位属性percentX percentY 说明

为了使位置关键帧在这样的系统中有用,我们需要它们能够以类似的自适应方式定位自己——我们不能简单地将它们定义为固定位置。
为了解决这个问题,同时保持关键帧系统的轻量级,我们提出了一种灵活的方法——在给定的坐标系中,每个关键帧的位置都用 (x,y) 坐标对表示:percentX percentY
这些坐标的含义取决于使用的坐标系类型(motion:keyPositionType ):parentRelative、deltaRelative或pathRelative。

注意

每个关键帧位置都是单独完成的——每个关键帧都可以使用自己的坐标系来表示,独立于其他。

2.motion:keyPositionType 坐标系类型()

1. parentRelative 
    相对父布局表示的坐标类型(此坐标系仅基于父尺寸)

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

-3.pathRelative
    最后一个坐标系被定义为相对于开始和结束状态之间的直线路径
parentRelative .png
deltaRelative.png
pathRelative.png

3: pathMotionArc 圆弧运动轨迹

ConstraintLayout 2.0.0 alpha 2 中,我们引入了一种实现完美弧线运动的新方法——而且它更易于使用。你只需要添加 motion:pathMotionArc 属性到起始 ConstraintSet, 从默认的直线运动切换到圆弧运动

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

1.圆弧轨迹类型

  
   <attr format="enum" name="pathMotionArc">
        <enum name="none" value="0"/>
        <enum name="startVertical" value="1"/>
        <enum name="startHorizontal" value="2"/>
        <enum name="flip" value="3"/>
    </attr>

a.startHorizontal 水平启动(横向): motion:pathMotionArc=”startHorizontal”


startHorizontal.gif

b.startVertical:垂直启动(纵向)
motion:pathMotionArc=”startVertical”

startVertical.gif

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

c.flip 具有翻转方向的中间关键帧

motion:pathMotionArc="flip"

flip.gif

4.transitionEasing 缓动曲线(类似插值器)

 <attr format="string|enum" name="transitionEasing">
    <enum name="standard" value="0"/>
    <enum name="accelerate" value="1"/>
    <enum name="decelerate" value="2"/>
    <enum name="linear" value="3"/>
</attr>    
  1. standard 标准模式
    通常用于将角色添加到非触摸驱动的动画中。它最适用于以静止开始和结束的元素
    [站外图片上传中...(image-c6adb-1643778430377)]


    标准模式.gif
  2. accelerate:加速模式
    将元素移出场景时通常使用加速。


    加速模式.gif

3.decelerate :减速模式
将元素移动到场景中时通常使用减速。


减速模式.gif
  1. cubic(float, float , float, float), 其中参数是 x1,y1,x2,y2 表示
    image.png

B: KeyAttribute 属性关键帧

属性关键帧可让您在动画期间的给定时间点指定小部件属性更改 - 换句话说,它们类似于位置关键帧,但适用于属性而不是位置。可以理解为关键位置的属性

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

1.支持的属性

您可以直接使用的属性是视图属性: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 中引入

2.自定属性义

您可以通过添加子元素在 ConstraintSets 和 KeyAttribute 元素中声明自定义属性<CustomAttribute>。该元素需要一个名称 ( attributeName),它是 getter/setter 的名称(减去 set/get 前缀),以及要插入或应用的值,使用以下属性之一指定:
customColorValue: 应用颜色值
customColorDrawableValue:应用颜色值,包装为可绘制对象
customIntegerValue: 应用一个整数值
customFloatValue: 应用浮点值
customStringValue: 应用一个字符串值
customDimension: 应用维度值
customBoolean: 应用一个布尔值

<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>

总结

根据谷歌开发者文章总结加上子理解写下的这篇博客,英文好的可以看原版.在这里简单的结束了下 位置关键帧以及属性关键帧,其他的几种暂时没学习回头补上.

参考文献

1.Google的MotionLayout介绍说明

2.MotionLayout的文档简介

3.MotionLayout 源码地址

4. 英文原版地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容