【Android】MotionLayout实现动画效果

【Android】MotionLayout实现开场动画

在移动应用开发中,动画不仅仅是美化界面的工具,它更是提升用户体验的关键手段。Android 平台一直以来都提供了丰富的动画框架,但随着应用复杂性的增加,开发者对动画的需求也变得更加复杂和多样化。为了更好地应对这些需求,Google 在 ConstraintLayout 的基础上推出了 MotionLayout

效果展示

先来看看MotionLayout可以实现的效果吧~

basic-horizontal-mot -original-original

来看看笔者用MotionLayout做的蒟蒻效果:

6748a7b1411f56f328fa -original-original

关于MotionLayout

如何去制作这样一个流畅的动画效果呢?我们直接进入本篇博客的主题:MotionLayout

MotionLayout简述

首先来简单介绍一下MotionLayout。MotionLayout 是 Android ConstraintLayout 的扩展,集布局和动画于一体,旨在简化复杂的界面过渡和动画效果的实现。与传统的动画框架相比,MotionLayout 更加声明性、更易于可视化,并且能够处理非常复杂的动画场景。通过 MotionLayout,开发者可以在布局文件中定义多个状态,并在这些状态之间进行平滑的过渡,从而实现丰富的动画效果,例如转场动画、导航菜单的展开与收起等。

QQ_1725026153876

这是Google官方文档中MotionLayout的介绍,我们可以看到它继承于ConstraintLayout,这在本文的后半部分,具体的代码操作中会有所体现,学习MotionLayout的使用可能需要对ConstraintLayout有一定的了解。

那么,MotionLayout是如何去实现动画的呢?所谓的声明性,可视性又是什么呢?又该如何定义多个状态,进行平滑过渡呢?我们接着往下看。

MotionScene

要做到动画效果的实现,我们离不开一个关键的配置文件:MotionScene。

它是一个 XML 文件,定义了动画的所有相关信息,包括状态、过渡、关键帧等。MotionScene 通过描述 ConstraintSet(状态集)、Transition(过渡)、KeyFrame(关键帧)等来组织和管理动画的逻辑。

MotionScene 的整体结构可以分为以下几个主要部分:

  1. ConstraintSet: 定义不同的布局状态(开始状态和结束状态)。
  2. Transition: 定义状态之间的过渡及其控制方式。
  3. KeyFrame: 定义动画过程中的关键变化点。
  4. OnSwipe: 定义与用户手势交互的动画触发器。

ConstraintSet

ConstraintSet 是 MotionScene 的基础部分,用于定义组件在不同状态下的布局约束。在 MotionScene 中,通常至少定义两个 ConstraintSet,分别对应 startend 状态。

每一个 ConstraintSet 都包含了布局中所有控件的约束信息。通过定义多个 ConstraintSet,你可以控制动画在不同状态下的表现。(一个ConstraintSet即为一个状态下,UI控件的集合)

以下是一些常用的属性:

ConstraintSet 中每个 Constraint 的属性基本与 ConstraintLayout 的属性相同。以下是一些常用属性:

  • layout_constraintStart_toStartOf: 将组件的开始边缘与另一个组件的开始边缘对齐。
  • layout_constraintEnd_toEndOf: 将组件的结束边缘与另一个组件的结束边缘对齐。
  • layout_constraintTop_toTopOf: 将组件的顶部与另一个组件的顶部对齐。
  • layout_constraintBottom_toBottomOf: 将组件的底部与另一个组件的底部对齐。
  • layout_widthlayout_height: 定义组件的宽度和高度。
  • rotation: 设置组件的旋转角度。
  • alpha: 设置组件的透明度。

开始状态与结束状态(Start and End States)

MotionLayout 的动画本质上是在两个状态之间进行转换:开始状态(start)和结束状态(end)。这两个状态定义了动画的起点和终点,分别通过 ConstraintSet 在 XML 中描述。

  • 开始状态(Start State):这是动画的初始状态,定义了组件的布局、大小、位置、旋转角度等属性。
  • 结束状态(End State):这是动画的最终状态,描述了动画结束时组件应达到的目标属性。

在动画开始时,组件处于 start 状态,随着用户的操作或代码控制,MotionLayout 会将组件逐步过渡到 end 状态。这个转换过程是通过 Transition 来定义和控制的。

例如:笔者制作的动画效果的配置文件如下:

    <ConstraintSet android:id="@+id/start"><Constraintandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:alpha="0.7"motion:layout_constraintEnd_toEndOf="parent"motion:layout_constraintStart_toStartOf="parent"motion:layout_constraintBottom_toTopOf="parent" /><Constraintandroid:id="@+id/rv_msg"android:layout_width="match_parent"android:layout_height="wrap_content"motion:layout_constraintStart_toEndOf="parent"motion:layout_constraintTop_toTopOf="@id/linearLayout" /><Constraintandroid:id="@+id/linearLayout"android:layout_width="match_parent"android:layout_height="60dp"android:layout_marginBottom="10dp"motion:layout_constraintTop_toBottomOf="parent" /></ConstraintSet><ConstraintSet android:id="@+id/end"><Constraintandroid:id="@+id/toolbar"motion:layout_constraintEnd_toEndOf="parent"android:layout_width="match_parent"android:layout_height="wrap_content"android:alpha="0.7"motion:layout_constraintTop_toTopOf="parent"motion:layout_constraintStart_toStartOf="parent" /><Constraintandroid:id="@+id/rv_msg"android:layout_width="match_parent"android:layout_height="0dp"motion:layout_constraintBottom_toTopOf="@id/linearLayout"motion:layout_constraintTop_toBottomOf="@+id/toolbar"motion:layout_constraintStart_toStartOf="parent" /><Constraintandroid:id="@+id/linearLayout"android:layout_width="match_parent"android:layout_height="60dp"android:layout_marginBottom="10dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintStart_toStartOf="parent" /></ConstraintSet>
  • start 状态下,所有元素(toolbarrv_msglinearLayout)都在屏幕外部,因此不可见。
  • end 状态下,所有元素都移入屏幕内,toolbar 位于顶部,rv_msgtoolbar 下面,并占据屏幕的中间部分,linearLayout 位于屏幕底部。

当 MotionLayout 执行从 startend 的过渡时,toolbarrv_msglinearLayout 将从屏幕外部滑动到它们在 end 状态下的位置,创建一个滑动进入的动画效果。

Transition

Transition 是 MotionLayout 中的关键概念,用于定义从一个状态(ConstraintSet)到另一个状态的过渡动画。Transition 不仅控制动画的时间和插值器,还可以定义触发动画的条件和动画的具体行为(例如响应触摸事件或特定的时间)。

basic-horizontal-mot -original-original

例如,在这个实例中,可以通过滑动来控制方块控件的位置,这一操作可以定义在Transition中。

在笔者制作的动画效果中,Transition如下:

    <Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="2000"motion:autoTransition="animateToEnd"></Transition>	
  • app:constraintSetStart: 定义动画的起始状态,这个属性引用了一个 ConstraintSet
  • app:constraintSetEnd: 定义动画的结束状态,这个属性也引用了一个 ConstraintSet
  • app:duration: 动画的持续时间,以毫秒为单位。

除了基本属性,Transition 还提供了一些高级属性和功能,帮助你更细致地控制动画行为。

触摸事件(OnSwipe 和 OnClick)

你可以通过 OnSwipeOnClick 来定义触摸事件,触发 Transition 的执行。

OnSwipe: 定义了在滑动手势下如何触发 Transition,例如上下滑动或左右滑动。

<OnSwipeapp:dragDirection="dragUp"app:touchAnchorId="@id/imageView"app:touchAnchorSide="bottom" />
  • app:dragDirection: 指定滑动的方向,例如 dragUp 表示向上滑动。
  • app:touchAnchorId: 触摸事件的锚点,即滑动时要跟踪的视图。
  • app:touchAnchorSide: 指定锚点的哪一侧被用作触摸参考点。

OnClick: 定义点击事件触发 Transition,例如点击某个按钮时触发动画。

<OnClickapp:targetId="@id/button"app:clickAction="transitionToEnd" />
  • app:targetId: 触发点击事件的目标视图 ID。
  • app:clickAction: 定义点击后的动作,例如 transitionToEnd 表示触发从 startend 的过渡。
自动过渡(AutoTransition)

Transition 还支持自动过渡,即在满足特定条件时自动触发动画。你可以通过以下属性控制自动过渡:

  • app:autoTransition
    设置自动过渡的类型。
    • jumpToEnd: 动画直接跳到结束状态。
    • animateToEnd: 动画自动播放到结束状态。
    • jumpToStart: 动画直接跳回开始状态。
    • animateToStart: 动画自动回到开始状态。

KeyFrame

KeyFrame 是 MotionLayout 中用于精确控制动画过程的工具。它允许你在动画的特定时间点(关键帧)对视图的属性进行自定义设置,以实现复杂的动画效果。KeyFrame 可以让你在动画过程中定义位置、属性变化、周期性动画等,从而获得更细致的动画表现。

其实就是实现帧动画

在 MotionLayout 中,KeyFrame 用于指定在动画过程中的某些关键时间点上视图的状态。这些关键时间点通常是动画的百分比位置(0% 到 100%),即动画开始到结束的过程中的特定位置。

可以实现如下的效果:

动画效果

KeyFrame 类型

MotionLayout 提供了几种不同类型的 KeyFrame,每种类型用于不同的动画控制需求:

  1. KeyPosition
  2. KeyAttribute
  3. KeyCycle
1. KeyPosition

KeyPosition 主要用于控制视图的位置变化。通过 KeyPosition,你可以定义在动画的特定时刻视图的位置(xy 坐标)。

属性

  • app:framePosition: 关键帧的位置,范围从 0 到 100,表示动画的百分比。
  • app:motionTarget: 关键帧作用的目标视图。
  • app:percentX: 目标视图在动画时刻的相对 X 坐标(0.0 到 1.0)。
  • app:percentY: 目标视图在动画时刻的相对 Y 坐标(0.0 到 1.0)。

示例

<KeyPositionapp:framePosition="50"app:motionTarget="@id/targetView"app:percentX="0.5"app:percentY="0.5" />

在这个示例中,KeyPosition 定义了在动画的 50% 位置上,targetView 的位置应为相对父视图的中心(50% X 和 50% Y)。

2. KeyAttribute

KeyAttribute 用于控制视图的属性变化,例如尺寸、透明度、旋转等。你可以在关键帧中定义这些属性在特定时刻的值。

属性

  • app:framePosition: 关键帧的位置,范围从 0 到 100,表示动画的百分比。
  • app:motionTarget: 关键帧作用的目标视图。
  • app:attributeName: 要设置的属性名称(如 alpharotationscaleXscaleY 等)。
  • app:attributeValue: 属性在关键帧时刻的值。

示例

<KeyAttributeapp:framePosition="50"app:motionTarget="@id/targetView"app:attributeName="alpha"app:attributeValue="0.5" />
3. KeyCycle

KeyCycle 用于控制周期性动画,即动画过程中的重复效果。它允许你创建周期性的动画效果,如摆动或波动。

属性

  • app:framePosition: 关键帧的位置,范围从 0 到 100,表示动画的百分比。
  • app:motionTarget: 关键帧作用的目标视图。
  • app:cycle: 循环次数或周期。
  • app:waveShape: 波形形状,例如 sinetriangle 等。
  • app:wavePeriod: 波形周期。

示例

<KeyCycleapp:framePosition="50"app:motionTarget="@id/targetView"app:waveShape="sine"app:wavePeriod="1"app:rotation="360" />

怎么创建MotionLayout

可以像写ConstraintLayout一样,直接在创建的时候就选择使用MotionLayout,但是笔者更加推荐先写一个ConstraintLayout,再转换为MotionLayout的方法。(对喜欢改UI的人比较友好)

首先我们拿到一个ConstraintLayout

QQ_1725028634488

右侧工具栏,启动!ComponentTree,启动!右键main然后点击Convert to MotionLayout,就可以自动转换成MotionLayout啦,同时也会自动创建一个MotionScene配置文件。

不想写代码怎么办

那么这个时候可能就有同学会问了,虽然已经把需要写的代码简化成这样了,但我还是不想写,怎么办?(谁问你了?)

不要慌,请看VCR:

QQ_1725028790092

我们把右侧工具栏拉出来,发现了…一个AndroidStudio自带的图形化工具!

可以在这里自由注册Constraint中的组件,也可以自由设置start以及end状态中组件的位置,大小,角度等等属性。

QQ_1725028892570

点击左上角的箭头,还可以直接设置Transition的属性,添加关键帧等等。

(但是这个只能作为便利开发的一种手段,笔者亲测感觉这个东西不是太好用,主要体现在设置填入的时候总是不及时反馈,有时候设置了许多东西,运行发现并未设置上,叫人抓狂得很)

结语

参考文档:

突破传统动画:探索MotionLayout的独特优势-腾讯云开发者社区-腾讯云 (tencent.com)

MotionLayout examples | Views | Android Developers (google.cn)

Android | MotionLayout入门级使用教程(一)_motionlayout的使用-CSDN博客

希望这篇文章可以给大家的UI开发做一些思路上的扩展~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/52889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何通过WinRAR软件有效禁止RAR压缩包内文件的修改

RAR压缩包作为一种广泛使用的文件格式&#xff0c;凭借其高压缩比和强大的功能&#xff0c;成为了许多用户保存和传输文件的首选。然而&#xff0c;在某些情况下&#xff0c;我们可能希望确保RAR压缩包内的文件不被随意修改或删除&#xff0c;以维护文件的安全性和完整性。本文…

【网络】数据链路层-MAC帧

数据链路层-以太网与ARP协议 文章目录 1.数据链路层2.以太网2.1什么是以太网2.2MAC帧格式 3.ARP协议3.1为什么有ARP协议&#xff1f;3.2ARP的定位3.3ARP协议工作流程3.4ARP数据格式 4.RARP协议 1.数据链路层 数据链路层是网络协议栈中最底层的内容&#xff0c;而在之前对其他…

恶劣天气下的目标检测新突破:多尺度退化建模与特征融合策略

更多优质内容&#xff0c;请关注公众号&#xff1a;智驾机器人技术前线 1.论文信息 论文标题&#xff1a;Degradation Modeling for Restoration-enhanced Object Detection in Adverse Weather Scenes 作者&#xff1a;Xiaofeng Wang, Xiao Liu, Hong Yang, Zhengyong Wang, …

阿里PAI-ChatLearn:大规模 Alignment高效训练框架正式开源

导读 ChatGPT是OpenAI开发的基于大型语言模型(LLM)的聊天机器人&#xff0c;以其令人惊叹的对话能力而迅速火爆并被广泛采用。ChatGPT 成功背后得益于大型语言模型生成领域的新训练范式&#xff1a;RLHF (Reinforcement Learning from Human Feedback)&#xff0c;即以强化学习…

PTA L1-028 判断素数

L1-028 判断素数&#xff08;10分&#xff09; 本题的目标很简单&#xff0c;就是判断一个给定的正整数是否素数。 输入格式&#xff1a; 输入在第一行给出一个正整数N&#xff08;≤ 10&#xff09;&#xff0c;随后N行&#xff0c;每行给出一个小于的需要判断的正整数。 …

利用clip模型实现text2draw

参考论文 实践 有数据增强的代码 import math import collections import CLIP_.clip as clip import torch import torch.nn as nn from torchvision import models, transforms import numpy as np import webp from PIL import Image import skimage import torchvision …

滚柱导轨:数控机床高效运行的驱动力

机床制造者最关心的莫过于机床的精度&#xff0c;刚性和使用寿命&#xff0c;对导轨系统的关注甚少。但导轨为机床功能的实现奠定了可靠的基础&#xff0c;各种类型的机床工作部件&#xff0c;都是利用控制轴在指定的导轨上运动。机床设计者根据机床的类型和用途选用各种不同形…

Python进阶04-网络编程

零、文章目录 Python进阶04-网络编程 1、计算机网络 网络相关知识请参考计算机网络详解 &#xff08;1&#xff09;IP地址的概念 IP 地址就是标识网络中设备的一个地址&#xff0c;好比现实生活中的家庭地址。 &#xff08;2&#xff09;IP地址的表现形式 IP 地址分为两类…

【Python Web开发】Flask+HTML学习笔记

目录 Flask框架一、安装flask库二、运行一个网页三、库函数及变量 HTML标签语言一、基本格式二、标签2.1 块级标签2.1.1 标题2.1.2 div2.1.3 图片2.1.4 列表2.1.5 表格 2.2 行内标签2.2.1 span2.2.2 超链接2.2.3 输入 2.3 其他标签2.3.1 提交表单 Flask框架 一、安装flask库 …

探索Unity与C#的无限潜能:从新手到高手的编程之旅

在数字创意与技术创新交织的今天&#xff0c;Unity游戏引擎凭借其强大的跨平台能力和灵活的编程接口&#xff0c;成为了无数开发者心中的首选。而C#&#xff0c;作为Unity的官方脚本语言&#xff0c;更是以其面向对象的特性和丰富的库支持&#xff0c;为游戏开发注入了无限可能…

Golang | Leetcode Golang题解之第375题猜数字大小II

题目&#xff1a; 题解&#xff1a; func getMoneyAmount(n int) int {f : make([][]int, n1)for i : range f {f[i] make([]int, n1)}for i : n - 1; i > 1; i-- {for j : i 1; j < n; j {f[i][j] j f[i][j-1]for k : i; k < j; k {cost : k max(f[i][k-1], f[…

【JAVA入门】Day28 - 数据结构

【JAVA入门】Day28 - 数据结构 文章目录 【JAVA入门】Day28 - 数据结构一、栈二、队列三、数组3.1 ArrayList 四、链表4.1 LinkedList 五、二叉树5.1 二叉查找树5.2 二叉树的遍历方式5.3 平衡二叉树5.4 平衡二叉树的旋转5.5 平衡二叉树需要旋转的几种情况 六、红黑树6.1 红黑规…

永成防回水防回气装置煤矿毫不犹豫选择

永成防回水防回气装置煤矿毫不犹豫选择&#xff0c;不敢说我们有多好&#xff0c;我们只把简单的事做好&#xff0c;用心服务&#xff0c;因为品质&#xff0c;所以信任。因为信任&#xff0c;所以值得选择。 本防回水防回气装置是一种用于煤矿瓦斯管路爆渣和燃烧时防止回火、…

3_1_PID控制原理

自从计算机进入控制领域以来&#xff0c;用数字计算机代替模拟计算机调节器组成计算机控制系统&#xff0c;不仅可以用软件实现PID控制算法&#xff0c;而且可以利用计算机的逻辑功能&#xff0c;使PID控制更加灵活。数字PID控制在生产过程中是一种最普遍采用的控制方法&#x…

[Algorithm][综合训练][奇数位丢弃][求和][计算字符串的编辑距离]详细讲解

目录 1.奇数位丢弃1.题目链接2.算法原理详解 && 代码实现 2.求和1.题目链接2.算法原理详解 && 代码实现 3.计算字符串的编辑距离1.题目链接2.算法原理详解 && 代码实现 1.奇数位丢弃 1.题目链接 奇数位丢弃 2.算法原理详解 && 代码实现 解法…

YOLOv9改进策略【损失函数篇】| 利用MPDIoU,加强边界框回归的准确性

一、背景 目标检测和实例分割中的关键问题&#xff1a; 现有的大多数边界框回归损失函数在不同的预测结果下可能具有相同的值&#xff0c;这降低了边界框回归的收敛速度和准确性。 现有损失函数的不足&#xff1a; 现有的基于 ℓ n \ell_n ℓn​范数的损失函数简单但对各种尺度…

Redis与SpringMVC的整合与最佳实践

整合Redis与Spring MVC&#xff08;现在通常是Spring Boot的一部分&#xff09;可以提高应用性能&#xff0c;特别是在处理大量数据缓存和会话状态管理方面。 下面是一些关于如何整合Redis与Spring MVC的最佳实践&#xff1a; 1. 引入依赖 首先&#xff0c;你需要在你的项目中…

【Java】Maven多环境切换实战(实操图解)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 Maven多环境配置学习4.2 切换环境4.2.1 先打包4.2.2 之后可以切换 五、总结…

【ACM独立出版 | 厦大主办】第五届计算机科学与管理科技国际学术会议(ICCSMT 2024,10月18-20)

第五届计算机科学与管理科技国际学术会议(ICCSMT 2024) 定于2024年10月18-20日在中国厦门举行。 会议旨在为从事“计算机科学”与“管理科技”研究的专家学者、工程技术人员、技术研发人员提供一个共享科研成果和前沿技术&#xff0c;了解学术发展趋势&#xff0c;拓宽研究思路…

设计模式结构型模式之适配器模式

结构型模式之适配器模式 一、概述和使用场景1、概述2、使用场景&#xff1a;3、主要分类 二、 代码示例1、类适配器模式2、接口适配器3、对象适配器 四、总结1、适配器模式2、适配器模式的优点3、适配器模式的缺点 一、概述和使用场景 1、概述 适配器模式是一种结构型设计模式…