博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
「译」MotionLayout介绍 (part III)
阅读量:5999 次
发布时间:2019-06-20

本文共 5118 字,大约阅读时间需要 17 分钟。

前言

在本系列的第一部分和第二部分中,我们介绍了 MotionLayout,并给出了各种示例:

  • basic motion
  • swipe handling
  • custom attribute interpolation
  • keyframes

第一部分和第二部分概述了 MotionLayout 中引入的基本概念。

现在将介绍如何在现有应用程序中使用 MotionLayout,并将其集成到现有布局(如 CoordinatorLayout,DrawerLayout或ViewPager)中。

配合 CoordinatorLayout 使用

(注意,MotionLayout 可以用来实现类似于 CoordinatorLayout的行为。我们将在下一篇文章中展示这些例子)

利用 MotionLayout 的一个简单方法让屏幕中的部分内容做指定动画。通过这种方式,你可以向应用程序中的现有布局添加更多有趣的运动,而不必从头开始。

例如,你想要的效果可能如下:

这里的基本思路是用 MotionLayout 替换 AppBarLayout 中的 Toolbar 元素。然后让 CoordinatorLayout 驱动动画进度。

由于你可以通过调用setProgress()来控制 MotionLayout 的过渡进度,因此我们可以创建一个简单的子类,通过监听 AppBarLayout 偏移量来跟踪改变:

package com.google.androidstudio.motionlayoutexample.utilsimport android.content.Contextimport android.support.constraint.motion.MotionLayoutimport android.support.design.widget.AppBarLayoutimport android.util.AttributeSetclass CollapsibleToolbar @JvmOverloads constructor(        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr), AppBarLayout.OnOffsetChangedListener {    override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) {        progress = -verticalOffset / appBarLayout?.totalScrollRange?.toFloat()!!    }    override fun onAttachedToWindow() {        super.onAttachedToWindow()        (parent as? AppBarLayout)?.addOnOffsetChangedListener(this)    }}复制代码

然后用这个子类代替 CoordinatorLayout XML 文件中的 Toolbar。

复制代码

接下来唯一要做的就是创建一个包含了我们想要动画的控件的 MotionLayout 文件。这里我们有一个 作为背景的 ImageView 和一个 TextView:

复制代码

最后在 MotionScene 中定义它的动画效果:

复制代码

配合 DrawerLayout 使用

DrawerLayout 是另一个 Android framework 中的类,用于打开一个侧边栏。

相比通常的菜单,我们可能希望来一些更有趣的东西:

和把 MotionLayout 整合到 CoordinatorLayout 中类似,我们需要创建一个设置 MotionLayout 进度的子类:

package com.google.androidstudio.motionlayoutexample.utilsimport android.content.Contextimport android.support.constraint.motion.MotionLayoutimport android.support.v4.widget.DrawerLayoutimport android.util.AttributeSetimport android.view.Viewclass DrawerContent @JvmOverloads constructor(        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr), DrawerLayout.DrawerListener {    override fun onDrawerStateChanged(newState: Int) {    }    override fun onDrawerSlide(drawerView: View, slideOffset: Float) {        progress = slideOffset    }    override fun onDrawerClosed(drawerView: View) {    }    override fun onDrawerOpened(drawerView: View) {    }    override fun onAttachedToWindow() {        super.onAttachedToWindow()        (parent as? DrawerLayout)?.addDrawerListener(this)    }}复制代码

这个子类将通过onDrawerSlide() 回调来跟踪过渡进度。

使用这个子类,我们可以很容易地在DrawerLayout中集成MotionLayout:

复制代码

这个 xml 文件像我们前面 CoordinatorLayout 例子一样,包含了几个简单控件。

下面是一个使用了 MotionLayout 的菜单文件 (menu file):

复制代码

MotionScene 文件只是旋转不同的元素 (检查 rotation 属性)

复制代码

在 ViewPager中使用

类似的,我们可能希望有一个有趣的 ViewPager 。

我们也可以使用类似的技巧来集成 ViewPager 。创建一个子类来传递当前的位置。

package com.google.androidstudio.motionlayoutexample.utilsimport android.content.Contextimport android.support.constraint.motion.MotionLayoutimport android.support.v4.view.ViewPagerimport android.util.AttributeSetclass ViewpagerHeader @JvmOverloads constructor(        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr), ViewPager.OnPageChangeListener {    override fun onPageScrollStateChanged(state: Int) {    }    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {        var numPages = 3        progress = (position + positionOffset) / (numPages - 1)    }    override fun onPageSelected(position: Int) {    }}复制代码

计算非常简单——onPageScrolled()给我们提供了页面的位置索引(我们有三个页面的时候,这里是0,1或2),偏移量(对应偏移位置从0到1)。动画的进度更新我们可以通过下面的公式来得到:

progress = (position + positionOffset) / (numPages-1)

配合 Lottie 使用

前面的例子用了简单的图片来作为头部。你也可以 Lottie集成到你的 MotionLayout中,然后直接设置它的进度从而播放它。

让我们把上一个例子改成 LottieAnimationView:

简单起见,我们把基于 MotionLayout 的 ViewPager Header 改成只包含一个 LottieAnimationView 的样式:

复制代码

在 MotionScene 中关键的修改是使用motion:progress属性:

复制代码

由于 LottieAnimationView 有一个setProgress() 函数,这将导致 MotionLayout 通过它直接播放 Lottie 的对应进度。

完整的 MotionScene 文件如下:

复制代码

总结

本篇介绍了如何在现有布局中轻松集成 MotionLayout。

你可以在 找到这些例子的源码。

本系列文章还有更多内容:

  • Introduction to MotionLayout ()
  • Custom attributes, image transitions, keyframes ()
  • Taking advantage of MotionLayout in your existing layouts (CoordinatorLayout, DrawerLayout, ViewPager) ()
  • All about Keyframes! ()
  • MotionLayout as a choreographer of root layout
  • Nesting MotionLayout & other Views
  • MotionLayout with fragments

转载地址:http://klzmx.baihongyu.com/

你可能感兴趣的文章
杭电2097
查看>>
『原创』用C++开发WM应用系列(1)——"Hello World" Pro!(上)
查看>>
Mac mongodb 配置安装
查看>>
06Mybatis_入门程序——根据用户的名字模糊查询返回List集合
查看>>
Flash: 涅磐与重生
查看>>
多窗口创建控件
查看>>
非常流行的十款 jQuery 插件推荐
查看>>
市场运行趋势该如何研判
查看>>
编写程序计算数组元素之和。要求编写函数三次,每次以不同的方法处理数组边界。...
查看>>
家德瑞程序员魔盒实例说明
查看>>
Axure实例演示—登录界面
查看>>
【VxWorks系列】任务间同步与通信之共享内存
查看>>
读取txt文件的简易算法
查看>>
使用DNSSCrypt解决DNS污染问题
查看>>
String不可变StringBuffer可变
查看>>
poj2593 Max Sequence(两个不相交字段的最大总和与)
查看>>
变化Android系统属性SystemProperties.set("sys.powerctl", "shutdown")关机分析...
查看>>
git日志的查看与修改
查看>>
异或巧用:Single Number
查看>>
简学LINGO(三)——实例篇
查看>>