Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性

2024-05-06 13:48

本文主要是介绍Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

动画入门和进阶文章列表:

Animation动画概述和执行原理
Android动画之补间动画TweenAnimation
Android动画之逐帧动画FrameAnimation
Android动画之插值器简介和系统默认插值器
Android动画之插值器Interpolator自定义
Android动画之视图动画的缺点和属性动画的引入
Android动画之ValueAnimator用法和自定义估值器
Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
Android动画之AnimatorSet联合动画用法
Android动画之LayoutTransition布局动画
Android动画之共享元素动画
Android动画之ViewPropertyAnimator(专用于view的属性动画)
Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
Android动画之ActivityOptionsCompat概述
Android动画之场景变换Transition动画的使用
Android动画之Transition和TransitionManager使用
Android动画之圆形揭露动画Circular Reveal

1 ObjectAnimator 概述

前面讲解了ValueAnimator和估值器,ValueAnimator只能对数值进行计算,要实现动画需要监听动画,然后获取数值,自己操作对象。不知道大家的感觉如何,我有两个两个感觉,一是这个动画有点复杂,另一个感觉是虽然叫做属性对象,但是完全没有感受到哪里跟属性有关。本篇文章主要讲解ObjectAnimator对象,这个对象继承自ValueAnimator,可以通过改变对象的属性,实现动画,是不是感觉ObjectAnimator叫做属性对象更合适。

在这里插入图片描述

ObjectAnimator继承自ValueAnimator,也是从API11才开始提供。

ValueAnimator类提供了把动画中的属性设置给目标对象的能力,只不过需要我们设置监听自己进行设置。ObjectAnimator可以设置动画目标对象(构造函数可以直接传入),构造函数中提供了将要作用于目标对象的属性名,ObjectAnimator运行过程中会把提供的属性利用目标对象提供的set函数设置给目标对象,有时也会调用目标对象的get函数获取属性值。简单说就是ObjectAnimator通过不断控制值的变化,再不断自动赋给对象的属性(调用目标对象的setXXX函数),从而实现动画效果。

属性动画原理:
属性动画并不是真正通过改变对象的属性来实现动画,而是通过调用目标对象指定的setXxx方法,其中xxx就是指定的属性名,对象不一定有xxx这个属性,只要有setXxx这个方法就可以。ObjectAnimator动画过程中会调用SetXxx函数设置xxx的值,然后其内部会主动调用invalidate()函数进行不停地重绘,这样就实现了动画效果。

ObjectAnimator类似ValueAnimator,不但可以直接利用代码生成,也可以利用xml文件实例化,xml方式不常用。
XML定义ObjectAnimator的标签为objectAnimator,API23以后也可以使用PropertyValuesHolder,具体使用方式在讲解ValueAnimator时已经讲解,这里不再重复。

ObjectAnimator实现动画的of方法

ofArgb(Object target, String propertyName, int... values)
ofArgb(T target, Property<T, Integer> property, int... values)
ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)
ofFloat(T target, Property<T, Float> property, float... values)
ofFloat(T target, Property<T, Float> xProperty, Property<T, Float> yProperty, Path path)
ofFloat(Object target, String propertyName, float... values)ofInt(T target, Property<T, Integer> xProperty, Property<T, Integer> yProperty, Path path)
ofInt(T target, Property<T, Integer> property, int... values)
ofInt(Object target, String propertyName, int... values)
ofInt(Object target, String xPropertyName, String yPropertyName, Path path)ofMultiFloat(Object target, String propertyName, float[][] values)
ofMultiFloat(Object target, String propertyName, Path path)
ofMultiFloat(Object target, String propertyName, TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values)
ofMultiInt(Object target, String propertyName, int[][] values)
ofMultiInt(Object target, String propertyName, Path path)
ofMultiInt(Object target, String propertyName, TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values)ofObject(T target, Property<T, V> property, TypeEvaluator<V> evaluator, V... values)
ofObject(Object target, String propertyName, TypeConverter<PointF, ?> converter, Path path)
ofObject(T target, Property<T, V> property, TypeConverter<PointF, V> converter, Path path)
ofObject(T target, Property<T, P> property, TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values)
ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)ofPropertyValuesHolder(Object target, PropertyValuesHolder... values)

2利用ObjectAnimator实现补间动画效果

2.1 平移动画

View有setTranslationX,setTranslationY实现坐标的改变
setTranslationX(float translationX) :以当前控件为原点,在x轴上移动
setTranslationY(float translationY) :以当前控件为原点,在Y轴上移动

ObjectAnimator实现平移:
向X轴正方向移动:

objectAnimator = ObjectAnimator.ofFloat(textView, "translationX", 100, 200, 300,400,500);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new LinearInterpolator());

在这里插入图片描述
Y轴方向移动不在演示

2.2 透明度

View有setAlpha函数控制透明度
ObjectAnimator实现透明度变化:

objectAnimator = ObjectAnimator.ofFloat(textView, "alpha", 0.1f,1.0f);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new LinearInterpolator());

在这里插入图片描述

2.3 缩放

View有setScaleX(float scaleX)和setScaleY(float scaleY)函数对View进行缩放。
ObjectAnimator实现缩放

objectAnimator = ObjectAnimator.ofFloat(textView, "scaleX", 0.1f,1.0f,2.0f,1.0f);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new LinearInterpolator());

在这里插入图片描述

2.4 旋转

View有setRotationX(float rotationX)和setRotationY(float rotationY),setRotation(rotation)函数设置旋转,
setRotationX:绕X轴旋转
setRotationY:绕Y轴旋转
setRotation: 绕中心旋转

ObjectAnimator实现旋转

objectAnimator = ObjectAnimator.ofFloat(textView, "rotation", 0,270);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new LinearInterpolator());

在这里插入图片描述

3 ObjectAnimator动画注意事项:重要

总结来自:https://developer.android.google.cn/guide/topics/graphics/prop-animation#java

动画一些特性:

  • duration 动画运行时长,如果不设置默认300ms
  • interpolation:设置动画运行过程中对应的动画完成状态(设置动画运行速率,类似动画设置了1000ms,可以让动画在运行到100ms时就展示动画完成时的状态)
  • 动画刷新频率,默认是每10ms刷新一次,但也跟系统忙碌程度有关,如果系统资源占用严重可能时间会延长。

重要:一下内容来自androidDeveloper,非常重要请大家关注
属性动画getXxx(),setXxx()函数和属性xxx的规则说明:

  • 如果ObjectAnimator想操作对象的foo属性实现动画操作,对象必须有相应的setFoo函数,
    因为ObjectAnimator会自动根据foo属性对应的setFoo函数去更新属性值。所以可以推测出ObjectAnimator会自动把属性转化成对应的set函数,会强制大写第一个字母,然后反射得到set函数,进行调用,所以ObjectAnimator初始化时属性首字母大小写无所谓,关键是除了首字母其他一定要和set函数对应。
  • 上面我们知道了对象setter函数的作用,那么getter函数有什么用处呢,ObjectAnimator指定values时,可以指定多个value,如果我们初始化时只指定了一个值,ObjectAnimator会把这个值作为动画结束状态的值,此时会调用getter函数作为动画初始状态的值。
  • 动画目标对象getter和setter函数的参数类型和ObjectAnimator设置动画开始和结束值的类型必须相同。
  • ObjectAnimator内部会主动调用目标对象的setter方法,但是这并不会导致view的重绘,需要你在setter方法中主动调用invalidate方法或者设置动画监听函数,在onAnimationUpdate的回调中调用invalidate方法。如果你要自己定义对象的setter方法,就要主动调用invalidate方法。

4 自定义ObjectAnimator属性

上面把view已经存在的平移,旋转,缩放,透明度属性利用ObjectAnimator进行了实现,接着将演示自定义ObjectAnimator属性的操作,通过上面的分析知道ObjectAnimator重要的点是属性和设置属性的set函数,以及主动调用invalidate函数,下面会通过一个例子来实现自定义ObjectAnimator属性的过程。
自定义view

public class ViewDemo22 extends View {private int color = Color.GREEN;private int radius = 100;private Paint mPaint;public int getColor() {return color;}public void setColor(int color) {this.color = color;mPaint.setColor(color);invalidate();}public int getRadius() {return radius;}public void setRadius(int radius) {this.radius = radius;invalidate();}public ViewDemo22(Context context) {this(context,null,0);}public ViewDemo22(Context context, @Nullable AttributeSet attrs) {this(context, attrs,0);}public ViewDemo22(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(color);mPaint.setStrokeWidth(5);mPaint.setStyle(Paint.Style.STROKE);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(getMeasuredHeight()/2,getMeasuredHeight()/2,radius,mPaint);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);if (width < 200){width = 200;}if (height < 200){height = 200;}if (width < height){setMeasuredDimension(height,height);}else{setMeasuredDimension(width,width);}}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);}
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"><com.ldx.canvasdrawdemo.ViewDemo22android:id="@+id/viewdemo"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"/></android.support.constraint.ConstraintLayout>
setContentView(R.layout.activity_main);
viewDemo22 = findViewById(R.id.viewdemo);ObjectAnimator objectAnimator = ObjectAnimator.ofInt(viewDemo22, "radius", 50, 300);
objectAnimator.setDuration(1000);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(-1);
objectAnimator.start();

在这里插入图片描述

改变颜色,没有设置插值器,只是简单数据改变:

ObjectAnimator objectAnimator = ObjectAnimator.ofInt(viewDemo22, "color", Color.RED, Color.GREEN);
objectAnimator.setDuration(1000);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(-1);
objectAnimator.start();

在这里插入图片描述

5 Xml 方式实现

用的不多,只简单举例

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:valueTo="200"android:valueType="floatType"android:propertyName="y"android:repeatCount="1"android:repeatMode="reverse"/>

ObjectAnimator objAnimator = (ObjectAnimator ) AnimatorInflater.loadAnimator(this,
R.animator.animator);

这篇关于Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/964525

相关文章

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Python3脚本实现Excel与TXT的智能转换

《Python3脚本实现Excel与TXT的智能转换》在数据处理的日常工作中,我们经常需要将Excel中的结构化数据转换为其他格式,本文将使用Python3实现Excel与TXT的智能转换,需要的可以... 目录场景应用:为什么需要这种转换技术解析:代码实现详解核心代码展示改进点说明实战演练:从Excel到

如何使用CSS3实现波浪式图片墙

《如何使用CSS3实现波浪式图片墙》:本文主要介绍了如何使用CSS3的transform属性和动画技巧实现波浪式图片墙,通过设置图片的垂直偏移量,并使用动画使其周期性地改变位置,可以创建出动态且具有波浪效果的图片墙,同时,还强调了响应式设计的重要性,以确保图片墙在不同设备上都能良好显示,详细内容请阅读本文,希望能对你有所帮助...

HTML5中下拉框<select>标签的属性和样式详解

《HTML5中下拉框<select>标签的属性和样式详解》在HTML5中,下拉框(select标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中选择值的方式,本文将深入探讨select标签的... 在html5中,下拉框(<select>标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中

C# string转unicode字符的实现

《C#string转unicode字符的实现》本文主要介绍了C#string转unicode字符的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录1. 获取字符串中每个字符的 Unicode 值示例代码:输出:2. 将 Unicode 值格式化

python安装whl包并解决依赖关系的实现

《python安装whl包并解决依赖关系的实现》本文主要介绍了python安装whl包并解决依赖关系的实现,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录一、什么是whl文件?二、我们为什么需要使用whl文件来安装python库?三、我们应该去哪儿下

Python脚本实现图片文件批量命名

《Python脚本实现图片文件批量命名》这篇文章主要为大家详细介绍了一个用python第三方库pillow写的批量处理图片命名的脚本,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言源码批量处理图片尺寸脚本源码GUI界面源码打包成.exe可执行文件前言本文介绍一个用python第三方库pi

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配

Java中实现订单超时自动取消功能(最新推荐)

《Java中实现订单超时自动取消功能(最新推荐)》本文介绍了Java中实现订单超时自动取消功能的几种方法,包括定时任务、JDK延迟队列、Redis过期监听、Redisson分布式延迟队列、Rocket... 目录1、定时任务2、JDK延迟队列 DelayQueue(1)定义实现Delayed接口的实体类 (