炫酷!MotionLayout 使用介绍 (第一章)

MotionLayout  是ConstrainLayout 2.0库中被引入的一个新类,帮助安卓开发者关联手势和组件动画。接下来的文章将介绍会如何在应用中添加和使用MotionLayoutjava

第一章将介绍MotionLayout的基础:android

  • MotionLayout 是什么?
  • ConstrainLayout 2.0MotionLayout添加到项目中
  • 如何使用 MotionLayout
  • ConstraintSets
  • MotionScene
  • 示例1:关联已有的布局文件
  • 处理OnSwipe
  • 示例2:自包含的MotionScene
  • MotionLayout属性
  • 总结

你能够在这里查看示例的源码ConstraintLayout examples github repositorgit

MotionLayout是什么?

安卓系统框架中已经提供下面几种方法在应用中使用动画:github

  • 动画矢量Drawable
  • 属性动画框架
  • LayoutTransition动画
  • 使用TransitionManager进行布局转换
  • CoordinatorLayout

这一部分将介绍MotionLayout与这些动画的不一样。MotionLayout就像它的名字同样,首先它是一个布局,能够放置组件。其次它仍是ConstrainLayout的子类,内置丰富的功能。建立MotionLayout的目的是用于下降布局过渡动画和复杂的手势处理之间的难度,你能够认为它拥有综合属性动画TransitionManager,和CoordinatorLayout的功能。面试

它拥有综合属性动画 TransitionManager,和 CoordinatorLayout的功能

使用MotionLayout你能够像TransitionManager同样经过两个布局文件描述布局的过渡动画,可是可使用任何属性(不只仅局局于布局属性)。还有它支持可循迹的过渡,就像CoordinatorLayout(能够经过滑动即刻响应过渡动画)。它支持经过滑动和关键帧自定义过渡动画。架构

MotionLayout是彻底声明式的

MotionLayout 的另一个关键区别是,它是彻底声明式的。只须要XML文件就能够描述一个复杂的过渡动画(若是你像经过代码来描述动画,系统提供的属性彻底能够知足需求)。app

MotionLayout工具

咱们相信这种声明式的规范将简化过渡动画,同时也有助于为 Android Studio 提供更好的图形化工具。(咱们如今正在积极的开发这样的工具,它如今还不可用。)框架

最后,做为ConstrainLayout 2.0的一部分,它最低支持安卓API 14,99.8%的设备均可以使用。ide

限制

不一样于TransitionManagerMotionLayout只能用于他的直接子组件。工具

什么时候使用MotionLayout

咱们设想到的使用MotionLayout的使用场景:当你须要移动,缩放或者动画实际的UI组件(按钮,标题栏等)来提供与用户的互动时。

如何使用MotionLayout

将ConstrainLayout 2.0和MotionLayout添加到项目中,只须要将下面的代码添加到Gradle文件中便可

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta1'
}

MotionLayoutConstrainLayout的子类,所以你能够把它看成一个普通的布局。将已经存在的ConstrainLayout布局转换成MotionLayout布局只须要将类名从:

<android.support.constraint.ConstraintLayout .../>

替换成

<android.support.constraint.motion.MotionLayout .../>

ConstrainLayout和MotionLayout的主要不一样是MotionLayout不是必须将实际描述信息包含在XML布局文件中。MotionLayout一般将这些信息保存在一个单独的XML文件(MotionScene)中并关联到布局文件,经过这种方式布局文件只须要包含它们的属性,无需包含位置信息和动画。

ConstraintSets

一般ConstrainSet将全部游戏布局文件中的全部的位置信息规则; 你可使用多个ConstrainSet,你能够决定将那些规则应用到布局中,在应用时这些查看不会被重建,只会修改他们的位置和大小。结合TransitionManager使用能够很容易的建立ConstrainLayout的动画。MotionLayout实际上也是源于这种思想,并添加了更丰富的功能。

MotionScene

MotionLayout的规范保存在一个单独的MotionSceneXML文件中,文件该存储在res / xml目录中。

image

一个MotionScene文件能够全部游戏动画所需的所用内容:

  • 包含的 ConstraintSets
  • 这些ConstraintSet之间的转换(过渡)
  • 关键帧,事件处理

例如,你能够将一个查看从屏幕的一侧拖拽到另外一侧:

示例1:关联布局文件

须要你使用ConstrainLayout建立³³两个ConstrainSet一个的英文初始位置(组件在屏幕的左面)一个是结束位置(组件在屏幕的右边)

初始位置:

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

结束位置:

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

使用这两个布局文件能够初始化两个ConstrainSet,并使用他们(使用若是TransitionManager会有动画的平滑过渡)。这种方式有一个问题是转化一旦开始就不会结束,你也不能告诉系统将转换挺在某个位置(你不能经过输入事件控制转换)。MotionLayout解决了这些问题。你可使用MotionLayout作一样的事,而且复用已存在的布局文件来初始化状态。首先须要为组件建立一个MotionLayout文件(motion_01_basic.xml):

<?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"
    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"
        tools:layout_editor_absoluteX="147dp"
        tools:layout_editor_absoluteY="230dp" />

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

文件布局引用中了一个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设置了默认的转换,设置了开始和结束ConstrainSet  (motion_01_cl_startmotion_01_cl_end),并转换为设置了OnSwipe处理。

OnSwipe

scene_01.xml文件中咱们在Transition中设置了OnSwipe处理器。处理器经过匹配用户的输入事件控制转换。

image

有一些属性你须要了解:

  • touchAnchorId:须要跟踪的对象
  • touchAnchorSide:跟踪手指的一侧(右/左/上/下)
  • dragDirection:跟踪手指运动的方向(dragRight / dragLeft / dragUp / dragDown将决定进度值的变化0-1)

示例2:自包含的MotionScene

示例1展现了如何快速的建立一个MotionLayout。,使用名单最终已了存在的布局文件MotionLayout还请当即获取iTunes直接在MotionScene文件中定义ConstraintSet。这样作有有如下好处:

  • 一个文件能够包含多个 ConstraintSet
  • 除了已有的功能外,还能够处理其余的属性和自定义属性
  • 面向将来:即将到来的Android Studio MotionEditor可能只支持自包含MotionScene文件
插值属性

MotionScene中文件ConstraintSet元素可使用的属性不只全部游戏经常使用的布局属性,位置除了状语从句:边距下面的属性也。能够在MotionLayout中使用:

alpha
visibility
elevation
rotation, rotation[X/Y]
translation[X/Y/Z]
scaleX/Y

让咱们为示例1从新建立一个新的自包含的MotionScene。文件MotionLayout文件除了引用了新的scene_02.xml状语从句:实例1中没有区别:

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

MotionScene文件中有明显的区别,Transition的设置相同,可是咱们把Start和结束直接定义在了XML文件中。和普通布局文件相比主要的区别是咱们没有指定具体的组件,而是把限定属性写在了Constraint元素中。

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

ConstraintSet

只须要将了解ConstrainSet是如何工做的,新的属性将替换到关联的组件上。只需将须要替换的属性所有包含到Constraint中。一般这会清除组件上的所用属性并将新的属性赋值到组件上。MotionLayout的属性

开发在中你可能会用到MotionLayout的下列属性:

  • app:layoutDescription=”reference”指定MotionSceneXML文件
  • app:applyMotionScene=”boolean” 是否应用MotionScene [default = true]
  • app:showPaths=”boolean”是否显示路径[default = false]。记得在发布版本中关闭
  • app:progress=”float” 指定转换的进度[0-1]
  • app:currentState=”reference” 指定一个ConstraintSet

总结

第一篇文章包含了MotionLayout的基础功能,你能够在这里查看源码:https://github.com/googlesamples/android-ConstraintLayoutExamples

接下来的文章中咱们将包含更多的讲解:

  • 自定义属性,图片变换,关键帧(第二部分)
  • 在现有的布局中使用MotionLayout(CoordinatorLayout,DrawerLayout,ViewPager)(第三部分)
  • 关于关键帧的全部!(第四部分)
  • MotionLayout做为根布局
  • 嵌套MotionLayout&其余的组件
  • MotionLayout和fragments

读者福利限时分享

Android开发资料+面试架构资料 免费分享 点击连接 便可领取

《Android架构师必备学习资源免费领取(架构视频+面试专题文档+学习笔记)》

相关文章
相关标签/搜索