【Android】属性动画

在属性动画出现之前,Android 系统提供的动画只有帧动画和 View 动画。View 动画我们都了解,它提供了 AlphaAnimation、RotateAnimation、TranslateAnimation、ScaleAnimation 这4种动画方式,并提供了 AnimationSet 动画集合来混合使用多种动画。随着属性动画的推出,View 动画不再风光。

相比属性动画,View 动画一个非常大的缺陷突显,其不具有交互性。当某个元素发生 View 动画后,其响应事件的位置依然在动画进行前的地方,所以 View 动画只能做普通的动画效果,要避免涉及交互操作。但是它的优点也非常明显:效率比较高,使用也方便。由于之前已有的动画框架 Animation 存在一些局限性,也就是动画改变的只是显示,但 View 的位置没有发生变化,View 移动后并不能响应事件,所以谷歌推出了新的动画框架,帮助开发者实现更加丰富的动画效果。在 Animator 框架中使用最多的就是 AnimatorSet 和 ObjectAnimator,配合使用 ObjectAnimator 进行更精细化的控制,控制一个对象和一个属性值,而使用多个 ObjectAnimator 组合到 AnimatorSet 形成一个动画。属性动画通过调用属性 get、set 方法来真实地控制一个 View 的属性值,因此,强大的属性动画框架基本可以实现所有的动画效果。

一、ObjectAnimator

ObjectAnimator 是属性动画最重要的类,创建一个 ObjectAnimator 只需通过其静态工厂类直接返还一个 ObjectAnimator 对象。参数包括一个对象和对象的属性名字,但这个属性必须有 get 和 set 方法,其内部会通过 Java 反射机制来调用 set 方法修改对象的属性值。下面看看平移动画是如何实现的,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Viewandroid:id="@+id/test_view"android:layout_width="100dp"android:layout_height="100dp"android:background="@android:color/holo_red_light"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val testView = findViewById<View>(R.id.test_view)val objectAnimator = ObjectAnimator.ofFloat(testView, "translationX", 200F)objectAnimator.setDuration(3000)objectAnimator.start()}
}

运行程序,效果如图1所示:
请添加图片描述

图1

通过 ObjectAnimator 的静态方法,创建一个 ObjectAnimator 对象,查看 ObjectAnimator 的静态方法 ofFloat(),源码如下所示:

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {ObjectAnimator anim = new ObjectAnimator(target, propertyName);anim.setFloatValues(values);return anim;
}

从源码可以看出第一个参数是要操作的 Object;第二个参数是要操作的属性;最后一个参数是一个可变的 float 类型数组,需要传进去该属性变化的取值过程,这里设置了一个参数,变化到200。与 View 动画一样,也可以给属性动画设置显示时长、插值器等属性。下面就是一些常用的可以直接使用的属性动画的属性值。

  • translationX 和 translationY:用来沿着 X 轴或者 Y 轴进行平移。
  • rotation、rotationX、rotationY:用来围绕 View 的支点进行旋转。
  • PrivotX 和 PrivotY:控制 View 对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认该支点位置就是 View 对象的中心点。
  • alpha:透明度,默认是1(不透明),0代表完全透明。
  • x 和 y:描述 View 对象在其容器中的最终位置。

需要注意的是,在使用 ObjectAnimator 的时候,要操作的属性必须要有 get 和 set 方法,不然 ObjectAnimator 就无法生效。如果一个属性没有 get、set 方法,也可以通过自定义一个属性类或包装类来间接地给这个属性增加 get 和 set 方法。现在来看看如何通过包装类的方法给一个属性增加 get 和 set 方法,代码如下所示:

class MyView(private val view: View) {fun getWidth(): Int {return view.layoutParams.width}fun setWidth(width: Int) {view.layoutParams.width = widthview.requestLayout()}
}

使用时只需要操作包类就可以调用 get、set 方法了:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val testView = findViewById<View>(R.id.test_view)val myView = MyView(testView)ObjectAnimator.ofInt(myView, "width", 500).setDuration(3000).start()}
}

运行程序,效果如图2所示:
请添加图片描述

图2

二、ValueAnimator

ValueAnimator 不提供任何动画效果,它更像一个数值发生器,用来产生有一定规律的数字,从而让调用者控制动画的实现过程。通常情况下,在 ValueAnimator 的 AnimatorUpdateListener 中监听数值的变化,从而完成动画的变换,代码如下所示:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val testView = findViewById<View>(R.id.test_view)val valueAnimator = ValueAnimator.ofFloat(0F, 100F)valueAnimator.setTarget(testView)valueAnimator.setDuration(3000).start()valueAnimator.addUpdateListener { animation ->val animatedValue = animation.animatedValue}}
}

三、动画的监听

完整的动画具有 start、Repeat、End、Cancel 这4个过程,代码如下所示:

val animator = ObjectAnimator.ofFloat(testView, "alpha", 1.5F)
animator.addListener(object : AnimatorListener {override fun onAnimationStart(animation: Animator) {}override fun onAnimationEnd(animation: Animator) {}override fun onAnimationCancel(animation: Animator) {}override fun onAnimationRepeat(animation: Animator) {}
})

大部分时候我们只关心 onAnimationEnd 事件,Android 也提供了 AnimatorListenterAdaper 来让我们选择必要的事件进行监听。

val animator = ObjectAnimator.ofFloat(testView, "alpha", 1.5F)
animator.addListener(object : AnimatorListenerAdapter() {override fun onAnimationEnd(animation: Animator) {super.onAnimationEnd(animation)}
})

四、组合动画(AnimatorSet)

AnimatorSet 类提供了一个 play() 方法,如果我们向这个方法中传入一个 Animator 对象(ValueAnimator 或 ObjectAnimator),将会返回一个 AnimatorSet.Builder 的实例。AnimatorSet 的 play() 方法源码如下所示:

public Builder play(Animator anim) {if (anim != null) {return new Builder(anim);}return null;
}

很明显,在 play() 方法中创建了一个 AnimatorSet.Builder 类,这个 Builder 类是 AnimatorSet 的内部类。我们来看看这个 Builder 类中有什么,代码如下所示:

public class Builder {private Node mCurrentNode;Builder(Animator anim) {mDependencyDirty = true;mCurrentNode = getNodeForAnimation(anim);}public Builder with(Animator anim) {Node node = getNodeForAnimation(anim);mCurrentNode.addSibling(node);return this;}public Builder before(Animator anim) {Node node = getNodeForAnimation(anim);mCurrentNode.addChild(node);return this;}public Builder after(Animator anim) {Node node = getNodeForAnimation(anim);mCurrentNode.addParent(node);return this;}public Builder after(long delay) {ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);anim.setDuration(delay);after(anim);return this;}
}

从源码中可以看出,Builder 类采用了建造者模式,每次调用方法时都返回 Builder 自身用于继续构建。AnimatorSet.Builder 中包括以下4个方法:

  • with(Animator anim):将现有动画和传入的动画同时执行。
  • before(Animator anim):将现有动画插入到传入的动画之前执行。
  • after(Animator anim):将现有动画插入到传入的动画之后执行。
  • after(long delay):将现有动画延迟指定毫秒后执行。

AnimatorSet 正是通过这几种方法来控制动画播放顺序的。这里再举一个例子,代码如下所示:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val testView = findViewById<View>(R.id.test_view)val animator1 = ObjectAnimator.ofFloat(testView, "translationX", 0.0F, 200.0F, 0F)val animator2 = ObjectAnimator.ofFloat(testView, "scaleX", 1.0F, 2.0F)val animator3 = ObjectAnimator.ofFloat(testView, "rotationX", 0.0F, 90.0F, 0.0F)val set = AnimatorSet()set.setDuration(3000)set.play(animator1).with(animator2).after(animator3)set.start()}
}

首先我们创建3个 ObjectAnimator,分别是 animator1、animator2 和 animator3,然后创建 AnimatorSet。在这里先执行 animator3,然后同时执行 animator1 和 animator2(也可以调用 set.playTogether(animator1,animator2) 来使这两种动画同时执行)。

运行程序,效果如图3所示:
请添加图片描述

图3

五、组合动画(PropertyValuesHolder)

除了上面的 AnimatorSet 类,还可以使用 PropertyValuesHolder 类来实现组合动画。不过这个组合动画就没有上面的丰富了,使用 PropertyValuesHolder 类只能是多个动画一起执行。当然我们得结合 ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder…values) 方法来使用。其第一个参数是动画的目标对象;之后的参数是 PropertyValuesHolder 类的实例,可以有多个这样的实例。具体代码如下所示:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val testView = findViewById<View>(R.id.test_view)val valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0F, 1.5F)val valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0F, 90.0F, 0.0F)val valuesHolder3 = PropertyValuesHolder.ofFloat("alpha", 1.0F, 0.3F, 1.0F)val objectAnimator = ObjectAnimator.ofPropertyValuesHolder(testView,valuesHolder1,valuesHolder2,valuesHolder3)objectAnimator.setDuration(3000).start()}
}

运行程序,效果如图4所示:
请添加图片描述

图4

六、在 xml 中使用属性动画

和 View 动画一样,属性动画也可以直接写在 xml 中。在 res 文件中新建 animator 文件夹,在里面新建一个 scale.xml,其内容如下所示:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:duration="3000"android:propertyName="scaleX"android:valueFrom="1.0"android:valueTo="2.0"android:valueType="floatType" />

在程序中引用 xml 定义的属性动画也很简单,代码如下所示:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val testView = findViewById<View>(R.id.test_view)val animator = AnimatorInflater.loadAnimator(this, R.animator.scale)animator.setTarget(testView)animator.start()}
}

运行程序,效果如图5所示:
请添加图片描述

图5

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

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

相关文章

35. 【Linux教程】Linux 修改用户组

前面小节介绍了如何添加用户组&#xff0c;本小节介绍如何给已经添加的新用户组修改信息&#xff0c;从 /etc/group 文件信息可以看到&#xff0c;用户组的信息比用户信息项少&#xff0c;和 usermod 命令类似&#xff0c;用户组的信息可以使用 groupmod 命令修改。 1. groupmo…

为了董宇辉,老婆跟我打起来了!写下一份深刻检讨

两个月前&#xff0c;因为讨论董宇辉小作文事件&#xff0c;跟老婆吵起来了。起因就为了两句话&#xff0c;写了这份检讨&#xff01;给大家分享一下。 老婆在网上刷了两晚关于董宇辉小作文的视频&#xff0c;一直为董宇辉喊冤、打抱不平。起初&#xff0c;我跟老婆的想法&…

怎样消除视频上的字幕和文字?3个方法值得推荐

怎样消除视频上的字幕和文字&#xff1f;消除视频上的字幕和文字不仅是一个常见的需求&#xff0c;更是一个对视频内容质量提升的关键步骤。特别是在处理从网络下载的带有水印或标识的视频时&#xff0c;这些额外的文字和信息往往会干扰观众的观看体验&#xff0c;甚至可能影响…

【数据结构】顺序表和链表的对比,在各种情况下如何选择

顺序表详细内容&#xff1a; 【数据结构】线性表 顺序表&#xff08;动态、静态分配&#xff0c;插入删除查找基本操作&#xff09;解析完整代码 单链表详细内容&#xff1a; 【数据结构】单链表解析完整代码&#xff08;插入、删除、尾插法、头插法、按值和按位查找、前插和后…

IDEA开发环境的安装与编写第一个程序

1.下载 IDEA&#xff08;全称IntelliJ IDEA&#xff09;是用于Java程序开发的集成环境&#xff08;也可用于其他语言&#xff09;&#xff0c;它在业界被公认是最好的Java开发工具之一&#xff0c;尤其在智能代码助手、代码自动提示、重构、J2EE支持、Ant、JUnit、CVS整合、代…

Mamba与MoE架构强强联合,Mamba-MoE高效提升LLM计算效率和可扩展性

论文题目&#xff1a; MoE-Mamba: Efficient Selective State Space Models with Mixture of Experts 论文链接&#xff1a; https://arxiv.org/abs/2401.04081 代码仓库&#xff1a; GitHub - llm-random/llm-random 作为大型语言模型&#xff08;LLM&#xff09;基础架构的后…

新一代科学计算与系统建模仿真平台MWORKS 2024a震撼发布:产品强势进化,更新亮点速览!

2月25日&#xff0c;同元软控成功举办MWORKS 2024产品发布会&#xff0c;会上公布了新版MWORKS的设计理念、关键技术、版本亮点、产品特性以及重大改进。当前&#xff0c;科学计算与系统建模仿真平台MWORKS 2024a已正式上线&#xff0c;开放下载。 MWORKS已成为全球第4个完整的…

C# 高阶语法 —— Winfrom链接SQL数据库的存储过程

存储过程在应用程序端的使用的优点 1 如果sql语句直接写在客户端&#xff0c;以一个字符串的形式体现的&#xff0c;提示不友好&#xff0c;会导致效率降低 2 sql语句写在客户端&#xff0c;可以利用sql注入进行攻击&#xff0c;为了安全性&#xff0c;可以把sql封装在…

嘉立创专业版导入SW模型的板框

1、SW新建一个需要的模型&#xff0c;例如下图&#xff0c; 2、点击另存为.dxf 文件&#xff08;是.dxf文件&#xff09; 3、选择要保存模型的视图&#xff0c;如上视图&#xff0c;确定后出现上视图板框形状&#xff0c;然后保存即可。 4、打开嘉立创&#xff0c;点击文件——…

整数编码【华为OD机试-JAVAPythonC++JS】

题目描述 实现一种整数编码方法&#xff0c;使得待编码的数字越小&#xff0c;编码后所占用的字节数越小。 编码规则如下: 编码时7位一组&#xff0c;每个字节的低7位用于存储待编码数字的补码 字节的最高位表示后续是否还有字节&#xff0c;置1表示后面还有更多的字节&#xf…

日志系统项目实现

日志系统的功能也就是将一条消息格式化后写入到指定位置&#xff0c;这个指定位置一般是文件&#xff0c;显示器&#xff0c;支持拓展到数据库和服务器&#xff0c;后面我们就知道如何实现拓展的了&#xff0c;支持不同的写入方式(同步异步)&#xff0c;同步:业务线程自己写到文…

万卡集群:字节搭建12288块GPU的单一集群

文章目录 论文Reference 论文 MegaScale: Scaling Large Language Model Training to More Than 10,000 GPUs 论文链接&#xff1a;https://arxiv.org/abs/2402.15627 从结构上讲&#xff0c;网络是基于Clos的“胖树”结构。其中一个改进是在顶层交换机上把上行与下行链路分开&…

三、《任务列表案例》前端程序搭建和运行

本章概要 整合案例介绍和接口分析 案例功能预览接口分析 前端工程导入 前端环境搭建导入前端程序 启动测试 3.1 整合案例介绍和接口分析 3.1.1 案例功能预览 3.1.2 接口分析 学习计划分页查询 /* 需求说明查询全部数据页数据 请求urischedule/{pageSize}/{currentPage} 请…

stm32触发硬件错误位置定位

1.背景 1. 项目中&#xff0c;调试过程或者测试中都会出现程序跑飞问题&#xff0c;这个时候问题特别难查找。 2. 触发硬件错误往往是因为内存错误。这种问题特别难查找&#xff0c;尤其是产品到了测试阶段&#xff0c;而这个异常复现又比较难的情况下&#xff0c;简直头疼。…

初学JavaScript总结

0 JavaScript html完成了架子&#xff0c;css做了美化&#xff0c;但是网页是死的&#xff0c;需要给他注入灵魂&#xff0c;所以接下来需要学习JavaScript&#xff0c;这门语言会让页面能够和用户进行交互。JavaScript又称为脚本语言&#xff0c;可以通过脚本实现用户和页面的…

Programming Abstractions in C阅读笔记:p306-p307

《Programming Abstractions in C》学习第75天&#xff0c;p306-p307总结&#xff0c;总计2页。 一、技术总结 1.Quicksort algorithm(快速排序) 由法国计算机科学家C.A.R(Charles Antony Richard) Hoare&#xff08;东尼.霍尔&#xff09;在1959年开发(develop), 1961年发表…

Mac 制作可引导安装器

Mac 使用U盘或移动固态硬盘制作可引导安装器&#xff08;以 Monterey 为例&#xff09; 本教程参考 Apple 官网相关教程 创建可引导 Mac OS 安装器 重新安装 Mac OS 相关名词解释 磁盘分区会将其划分为多个单独的部分&#xff0c;称为分区。分区也称为容器&#xff0c;不同容器…

VR虚拟现实技术应用到猪抗原体检测的好处

利用VR虚拟仿真技术开展猪瘟检测实验教学确保生猪产业健康发展 为了有效提高猪场猪瘟防控意识和检测技术&#xff0c;避免生猪养殖业遭受猪瘟危害&#xff0c;基于VR虚拟仿真技术开展猪瘟检测实验教学数据能大大推动基层畜牧养殖业持续稳步发展保驾护航。 一、提高实验效率 VR虚…

鲲鹏arm64架构下安装KubeSphere

鲲鹏arm64架构下安装KubeSphere 官方参考文档: https://kubesphere.io/zh/docs/quick-start/minimal-kubesphere-on-k8s/ 在Kubernetes基础上最小化安装 KubeSphere 前提条件 官方参考文档: https://kubesphere.io/zh/docs/installing-on-kubernetes/introduction/prerequi…

基于大模型思维链(Chain-of-Thought)技术的定制化思维链提示和定向刺激提示的心理咨询场景定向ai智能应用

本篇为个人笔记 记录基于大模型思维链&#xff08;Chain-of-Thought&#xff09;技术的定制化思维链提示和定向刺激提示的心理咨询场景定向ai智能应用 人工智能为个人兴趣领域 业余研究 如有错漏欢迎指出&#xff01;&#xff01;&#xff01; 目录 本篇为个人笔记 记录基…