Android初探Motionlayout,MotionScene,KeyFrameSet实现动画,曲线

最近有点闲,看了看新东西,无意间发现了Motionlayout这个东西,挺有趣的,真正项目能不能用上先两说,就当扩展知识库了

ConstraintLayout 是他的直接父类,也就是说约束布局的所有属性他也都能用

public class MotionLayout extends ConstraintLayout 

先说怎么引用

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-rc1'

再看效果实现


旋转变大直线.gif

这个东西可以实现很多酷炫的动画效果,我这个旋转只是冰山一角,有空再深入了解吧

在布局文件中写下这个控件然后一定记得给他的子view赋上id,后边要用

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/motion_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    app:motionDebug="SHOW_PATH"
    app:layoutDescription="@xml/activity_motionlayout_scene">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <SeekBar
        android:id="@+id/progress"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

这里边最关键的地方就是app:layoutDescription这个属性,需要配置MotionScene xml文件。这就类似于我们平常自定义的drawable文件。app:motionDebug="SHOW_PATH" 调试属性是可以预览动画的运动轨迹。

接下来是motionscen里边的写法,动画控制都在这个xml里实现,基本的动画效果都可以实现,并且跟你的手势或者点击联动,其中设置关键帧是调整动画效果的重中之中,我接下来放的三个例子都是基于手势滑动完成的动画,先看个普通的直线运动

<?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/btn_start">
        <Constraint
            android:id="@+id/btn"
            android:layout_width="100dp"
            android:layout_height="60dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/btn_end">
        <Constraint
            android:id="@+id/btn"
            android:layout_width="100dp"
            android:layout_height="60dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent" />
    </ConstraintSet>
    
    <Transition
        android:id="@+id/btn_transition"
        app:constraintSetEnd="@id/btn_end"
        app:constraintSetStart="@+id/btn_start"
        app:duration="2000">
      
        <OnSwipe app:touchAnchorId="@id/btn" />
    </Transition>
</MotionScene>
直线.gif
  <ConstraintSet android:id="@+id/btn_end">
        <Constraint
            android:id="@+id/btn"
            android:layout_width="100dp"
            android:layout_height="60dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent" />
    </ConstraintSet>

如果把结束位置的宽高变一下,那么这个动画就会变成这样


直线变大.gif

这个是不加关键帧的一个普通直上直下的动画写法,这个MotionScene其实Androidstudio里边可以自动生成,你只需要自己去写上对应id和动画效果就行了,或者自己去xml文件夹创建,效果是一样的,最终都是要写到布局文件的app:layoutDescription这个属性中,MotionScene.xml可以理解为是布局文件中Motionlayout这个布局中的子view的解释文件,解释他如何去运动,类似style
这个里边ConstraintSet 是用来表示motionlayout里边的子view的约束和位置的,之前在布局文件里我不是没有定位置么,可以在这里边做,然后id要对应上子viewid,写了两个给上动画开始和动画结束的位置,中间的过程系统会自动帮你实现,不做任何操作的时候就默认走直线了。
Transition是用来控制动画的,可以叫他控制器,这里边填写上开始和结束的constraintset的id,然后可以表明运动时间app:duration="2000",还可以表明通过什么操作开始运动 <OnSwipe>表示根据手势滑动,而之前说的关键帧<KeyFrameSet>也是写在控制器里的,开始的曲线运动就是通过这个实现


旋转变大直线.gif

旋转曲线.gif

这是控制器里的xml写法

 <Transition
        android:id="@+id/btn_transition"
        app:constraintSetEnd="@id/btn_end"
        app:constraintSetStart="@+id/btn_start"
        app:duration="2000">
        <KeyFrameSet>
            <KeyPosition
                app:framePosition="50"
                app:motionTarget="@id/btn"
                app:pathMotionArc="flip"
                app:percentY="0.5" />

            <KeyPosition
                app:framePosition="25"
                app:motionTarget="@id/btn"
                app:pathMotionArc="flip"
                app:percentX="0.25" />

            <KeyPosition
                app:framePosition="75"
                app:motionTarget="@id/btn"
                app:pathMotionArc="flip"
                app:percentX="1" />

            <KeyPosition
                app:framePosition="25"
                app:keyPositionType="parentRelative"
                app:motionTarget="@id/btn"
                app:percentX="0.7"
                app:percentY="0.6" />
            <KeyPosition
                app:framePosition="50"
                app:keyPositionType="parentRelative"
                app:motionTarget="@id/btn"
                app:percentX="0.85" />
            <KeyPosition
                app:framePosition="75"
                app:keyPositionType="parentRelative"
                app:motionTarget="@id/btn"
                app:percentX="0.7"
                app:percentY="0.4" />

<!--            apply other animation attributes-->
<!--            前半段的动画效果:逆时针旋转一圈-->
            <KeyAttribute
                android:rotation="-360"
                app:framePosition="50"
                app:motionTarget="@id/btn" />
            <!--后半段的动画效果:逆时针旋转一圈-->
            <KeyAttribute
                android:rotation="-720"
                app:framePosition="100"
                app:motionTarget="@id/btn" />
        </KeyFrameSet>

        <OnSwipe app:touchAnchorId="@id/btn" />
    </Transition>

其中KeyPosition就是具体到某个点的时候view所处的位置 通过这两个属性控制 app:percentX="0.7" app:percentY="0.6" 范围0-1代表所处xy轴百分比位置,而 app:framePosition="25"就是代表了当前动画运动到什么进度了,1-100 的范围 50代表运动到一半了连起来就是,动画进行到25%的时候view的坐标在x轴的70%y轴的60%的位置上,然后我们的曲线路径就是通过加多个关键帧实现的效果

KeyAttribute这个是代表属性变化,比如现在的转转效果android:rotation就是加在这里边,同样的可以加android:alpha做渐变透明或者其他效果,我就不展示了。

app:keyPositionType="parentRelative"这个属性是用来表示你是基于那个坐标系来运动的,比如parentRelative就是基于你的父布局一般用这个就够了,其他两个我还没研究明白
就这样吧

写布局就用约束布局加线性布局加相对布局组合着用吧

layout_constraintLeft_toLeftOf 我的左边在...的左边
layout_constraintLeft_toRightOf 我的左边在...的右边
layout_constraintRight_toLeftOf 我的右边在...的左边
layout_constraintRight_toRightOf 我的右边在...的右边
layout_constraintTop_toTopOf 我的上边在...的上边
layout_constraintTop_toBottomOf 我的上边在...的下边
layout_constraintBottom_toTopOf 我的下边在...的上边
layout_constraintBottom_toBottomOf 我的下边在...的下边
layout_constraintBaseline_toBaselineOf 多用于文字底线对齐
居中就是top-top bottom-bottom left-left right-right全部填父布局
这个控件写完 每个view的属性一大摞 但是页面整体层级很浅,对性能也算是一定的提升,再有就是可以预览界面拖拽布局,方便的很
尤其是你在写一些item的布局时,里边标签一大堆,用相对布局跟线性布局真的写着很累心,层级一多看着也很累心,希望用约束布局的越来越多

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