MotionLayout介绍

MotionLayout

本文是对Introduction to MotionLayout的翻译,本身可能翻译的有点很差,欢迎你们批评指正。侵权删。php

MotionLayout是一个在ConstraintLayout2.0版本库的时候添加的一个新的类,能够帮助开发者处理一些动画。android

Android framework已经提供了如此多的方式来帮咱们在应用中添加动画,app

  • Drawable矢量图
  • 属性动画
  • CoordinatorLayout
  • LayoutTransition animations
  • 利用TransitionManager的Layout transitions

那么MotionLayout与它们有什么不一样的地方?ide

  • MotionLayout是ConstraintLayout的一个子类,受益于ConstraintLayout丰富的特性
  • MotionLayout让layout布局元素可以在动画过渡期间也可以响应用户的UI交互

何时使用它?

当想要对与用户有直接交互的UI元素作动画时。布局

什么是对与用户有着直接交互的UI元素?就是用户的点击,滑动等动做。gradle

添加MotionLayout到你的项目

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha2'
}
复制代码

使用MotionLayout

MotionLayout是ConstraintLayout的子类。要想已有的ConstraintLayout变成MotionLayout只须要在具体的xml中,将:动画

<android.support.constraint.ConstraintLayout .../>
复制代码

改为google

<android.support.constraint.motion.MotionLayout .../>
复制代码

MotionLayout动画的具体的描述文件并无包含在定义MotionLayout的layout文件中,而是定义在了一个单独的xml文件(一个MotionScene文件)。spa

MotionScene

就如同以前所说,描述MotionLayout的动画的具体信息被定义在了一个单独的xml文件,MotionScene,一般存储在res/xml目录下翻译

如图所述,一个MotionScene一般包含以下的内容

  • 所使用的ConstraintSets
  • 所使用的ConstraintSets的transition(过渡阶段)
  • keyframes(关键帧)

就像下面的例子,咱们经过使用手指拖动一个简单的view从屏幕的一端滑动至另外一端,如何作到呢?

实现1:引用已有的layouts

一个指向初始的layout(view在屏幕左端),一个指向结束的layout(view在屏幕的右端),咱们须要定义两个layout

view在左端的layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
复制代码

view在右端的layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
复制代码

而后定义一个MotionLayout文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout 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/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true">

    <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" />

</android.support.constraint.motion.MotionLayout>
复制代码

注意这个layout文件指向了一个MotionScene文件---scene_01

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition motion:constraintSetStart="@layout/motion_01_cl_start" motion:constraintSetEnd="@layout/motion_01_cl_end" motion:duration="1000">
        <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" />
    </Transition>

</MotionScene>
复制代码

scene_01经过指定开始和结束的ConstraintSet(motion_01_cl_startmotion_01_cl_end,规定了过渡动画。注意,咱们指定了OnSwipe标签在transition中

OnSwipe标签

scene_01.xml文件中,咱们指定了一个OnSwipe标签,在一个Transition标签中,做用是依据咱们的手指的动做,来让动画发生。

OnSwipe的具体的各类属性

touchAnchorId:咱们想要作动画的object对象,(这里是@+id/button

touchAnchorSide:object的边,(right/left/top/bottom)

dragDirection:咱们所想要追踪的手指动做的方向(dragRight/dragLeft/dragUp/dragDown)

实现2:将ConstraintSets直接定义在MotionScene中

第一种实现方式重用了layout(基于ConstraintLayout)

MotionLayout一样支持直接在MotionScene中定义ConstraintSets,这带来了以下优点:

  • 只须要一个文件,就能够包括全部的ConstraintSets
  • 方便处理attributes
  • 将来Android Studio将只支持这种将ConstraintSets直接定义在MotionScene中的方式

让咱们将ConstraintSets直接定义在MotionScene中,达到和实现1同样的效果

咱们定义一个与实现1中同样的MotionLayout文件,只须要引用scene_02.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/motionLayout" app:layoutDescription="@xml/scene_02" android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:text="Button" />

</android.support.constraint.motion.MotionLayout>
复制代码

scene_02.xml中,Transition标签内部是一致的,区别在于咱们直接将startend的Constrait定义在了文件中。并由一个ConstraintSet标签包含着。

<?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:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">
        <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" />
    </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" />
    </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" />
    </ConstraintSet>

</MotionScene>
复制代码

能够被自动插值的属性(Interpolated Attributes)

在Constraint标签中除了能够定义元素的位置以外,还能够定义一些其余的属性,MotionLayout将自动地为这些属性生成中间的过渡状态,也就是插值。

alpha

visibility

elevation

rotation,rotation[x / y]

translation[x / y / z]

scaleX / Y

相似于下面的形式

<Constraint android:id="@id/content" android:layout_width="0dp" android:layout_height="match_parent" motion:layout_constraintWidth_default="percent" motion:layout_constraintWidth_percent="1" android:scaleX="0.8" android:scaleY="0.8" motion:layout_constraintLeft_toRightOf="@+id/button" motion:layout_constraintTop_toTopOf="parent"/>
复制代码

MotionLayout能够定义的属性

MotionLayout提供了一些属性

app:layoutDescription="reference",指向一个MotionScene XML文件

app:applyMotionScene="boolean"是否使用MotionScene,默认为true

app:showPaths="boolean"展现motion 路径,默认为false,app正式发布的时候要记得关闭

app:pregress="float"明确指定中间进度,区间在0到1

app:currentState="reference"强制一个特定的ConstraintSet

这篇文章只是MotionLayout的基础的功能的一个介绍,MotionLayout可以实现的功能远不止如此。

相关文章
相关标签/搜索