上期的内容,对于大多数简单的属性动画场景已经够用了。这期的内容主要针对两个方面:
1. 针对特殊类型的属性来做属性动画;
2. 针对复杂的属性关系来做属性动画。
TypeEvaluator

关于 ObjectAnimator,上期讲到可以用 ofInt() 来做整数的属性动画和用 ofFloat() 来做小数的属性动画。这两种属性类型是属性动画最常用的两种,不过在实际的开发中,可以做属性动画的类型还是有其他的一些类型。当需要对其他类型来做属性动画的时候,就需要用到 TypeEvaluator 了。
ArgbEvaluator

TypeEvaluator 最经典的用法是使用 ArgbEvaluator 来做颜色渐变的动画。

ObjectAnimator animator = ObjectAnimator.ofInt(view, “color”, 0xffff0000, 0xff00ff00);
animator.setEvaluator(new ArgbEvaluator());
animator.start();

另外,在 Android 5.0 (API 21) 加入了新的方法 ofArgb(),所以如果你的 minSdk 大于或者等于 21(哈哈哈哈哈哈哈哈),
你可以直接用下面这种方式:
ObjectAnimator animator = ObjectAnimator.ofArgb(view, “color”, 0xffff0000, 0xff00ff00);
animator.start();

自定义 Evaluator
如果你对 ArgbEvaluator 的效果不满意,或者你由于别的什么原因希望写一个自定义的 TypeEvaluator,你可以这样写:
// 自定义 HslEvaluator
private class HsvEvaluator implements TypeEvaluator {
float[] startHsv = new float[3];
float[] endHsv = new float[3];
float[] outHsv = new float[3];

        @Overridepublic Integer evaluate(float fraction, Integer startValue, Integer endValue) {// 把 ARGB 转换成 HSVColor.colorToHSV(startValue, startHsv);Color.colorToHSV(endValue, endHsv);// 计算当前动画完成度(fraction)所对应的颜色值if (endHsv[0] - startHsv[0] > 180) {endHsv[0] -= 360;} else if (endHsv[0] - startHsv[0] < -180) {endHsv[0] += 360;}outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction;if (outHsv[0] > 360) {outHsv[0] -= 360;} else if (outHsv[0] < 0) {outHsv[0] += 360;}outHsv[1] = startHsv[1] + (endHsv[1] - startHsv[1]) * fraction;outHsv[2] = startHsv[2] + (endHsv[2] - startHsv[2]) * fraction;// 计算当前动画完成度(fraction)所对应的透明度int alpha = startValue >> 24 + (int) ((endValue >> 24 - startValue >> 24) * fraction);// 把 HSV 转换回 ARGB 返回return Color.HSVToColor(alpha, outHsv);}}ObjectAnimator animator = ObjectAnimator.ofInt(view, "color", 0xff00ff00);

// 使用自定义的 HslEvaluator
animator.setEvaluator(new HsvEvaluator());
animator.start();

ofObject()
借助于 TypeEvaluator,属性动画就可以通过 ofObject() 来对不限定类型的属性做动画了。方式很简单:

为目标属性写一个自定义的 TypeEvaluator
使用 ofObject() 来创建 Animator,并把自定义的 TypeEvaluator 作为参数填入
private class PointFEvaluator implements TypeEvaluator {
PointF newPoint = new PointF();

@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {float x = startValue.x + (fraction * (endValue.x - startValue.x));float y = startValue.y + (fraction * (endValue.y - startValue.y));newPoint.set(x, y);return newPoint;
}

}

ObjectAnimator animator = ObjectAnimator.ofObject(view, “position”,
new PointFEvaluator(), new PointF(0, 0), new PointF(1, 1));
animator.start();

另外在 API 21 中,已经自带了 PointFEvaluator 这个类,所以如果你的 minSdk 大于或者等于 21(哈哈哈哈哈哈哈哈),上面这个类你就不用写了,直接用就行了。

ofMultiInt() ofMultiFloat()

在 API 引入的新的方法还有 ofMultiInt() 和 ofMultiFloat() 等,用法也很简单,不过实用性就低了一些。你有兴趣的话可以去做一下了解,这里不在多做介绍。
以上这些就是对 TypeEvaluator 的介绍。它的作用是让你可以对同样的属性有不同的解析方式,对本来无法解析的属性也可以打造出你需要的解析方式。有了 TypeEvaluator,你的属性动画就有了更大的灵活性,从而有了无限的可能。
TypeEvaluator 是本期的第一部分内容:针对特殊的属性来做属性动画,它可以让你「做到本来做不到的动画」。接下来是本期的第二部分内容:针对复杂的属性关系来做动画,它可以让你「能做到的动画做起来更简单」。
PropertyValuesHolder 同一个动画中改变多个属性

很多时候,你在同一个动画中会需要改变多个属性,例如在改变透明度的同时改变尺寸。如果使用 ViewPropertyAnimator,你可以直接用连写的方式来在一个动画中同时改变多个属性:
view.animate()
.scaleX(1)
.scaleY(1)
.alpha(1);
而对于 ObjectAnimator,是不能这么用的。不过你可以使用 PropertyValuesHolder 来同时在一个动画中改变多个属性。

PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat(“scaleX”, 1);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat(“scaleY”, 1);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat(“alpha”, 1);

ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder1, holder2, holder3)
animator.start();
PropertyValuesHolder 的意思从名字可以看出来,它是一个属性值的批量存放地。所以你如果有多个属性需要修改,
可以把它们放在不同的 PropertyValuesHolder 中,然后使用 ofPropertyValuesHolder() 统一放进 Animator。
这样你就不用为每个属性单独创建一个 Animator 分别执行了。

AnimatorSet 多个动画配合执行

有的时候,你不止需要在一个动画中改变多个属性,还会需要多个动画配合工作,比如,在内容的大小从 0 放大到 100% 大小后开始移动。这种情况使用 PropertyValuesHolder 是不行的,因为这些属性如果放在同一个动画中,需要共享动画的开始时间、结束时间、Interpolator 等等一系列的设定,这样就不能有先后次序地执行动画了。
这就需要用到 AnimatorSet 了。

ObjectAnimator animator1 = ObjectAnimator.ofFloat(...);animator1.setInterpolator(new LinearInterpolator());ObjectAnimator animator2 = ObjectAnimator.ofInt(...);animator2.setInterpolator(new DecelerateInterpolator());AnimatorSet animatorSet = new AnimatorSet();

// 两个动画依次执行
animatorSet.playSequentially(animator1, animator2);
animatorSet.start();
使用 playSequentially(),就可以让两个动画依次播放,而不用为它们设置监听器来手动为他们监管协作。
AnimatorSet 还可以这么用:

// 两个动画同时执行
animatorSet.playTogether(animator1, animator2);
animatorSet.start();
以及这么用:

// 使用 AnimatorSet.play(animatorA).with/before/after(animatorB)
// 的方式来精确配置各个 Animator 之间的关系
animatorSet.play(animator1).with(animator2);
animatorSet.play(animator1).before(animator2);
animatorSet.play(animator1).after(animator2);
animatorSet.start();
有了 AnimatorSet ,你就可以对多个 Animator 进行统一规划和管理,让它们按照要求的顺序来工作。
PropertyValuesHolders.ofKeyframe() 把同一个属性拆分

除了合并多个属性和调配多个动画,你还可以在 PropertyValuesHolder 的基础上更进一步,通过设置 Keyframe (关键帧),把同一个动画属性拆分成多个阶段。例如,你可以让一个进度增加到 100% 后再「反弹」回来。
// 在 0% 处开始
Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
// 时间经过 50% 的时候,动画完成度 100%
Keyframe keyframe2 = Keyframe.ofFloat(0.5f, 100);
// 时间见过 100% 的时候,动画完成度倒退到 80%,即反弹 20%
Keyframe keyframe3 = Keyframe.ofFloat(1, 80);
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe(“progress”, keyframe1, keyframe2, keyframe3);

ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder);
animator.start();

第二部分,「关于复杂的属性关系来做动画」,就这么三种:
1. 使用 PropertyValuesHolder 来对多个属性同时做动画;
2. 使用 AnimatorSet 来同时管理调配多个动画;
3. PropertyValuesHolder 的进阶使用:使用 PropertyValuesHolder.ofKeyframe() 来把一个属性拆分成多段,执行更加精细的属性动画。

ValueAnimator 最基本的轮子

额外简单说一下 ValuesAnimator。很多时候,你用不到它,只是在你使用一些第三方库的控件,而你想要做动画的属性却没有 setter / getter 方法的时候,会需要用到它。
除了 ViewPropertyAnimator 和 ObjectAnimator,还有第三个选择是 ValueAnimator。ValueAnimator 并不常用,因为它的功能太基础了。ValueAnimator 是 ObjectAnimator 的父类,实际上,ValueAnimator 就是一个不能指定目标对象版本的 ObjectAnimator。ObjectAnimator 是自动调用目标对象的 setter 方法来更新目标属性的值,以及很多的时候还会以此来改变目标对象的 UI,而 ValueAnimator 只是通过渐变的方式来改变一个独立的数据,这个数据不是属于某个对象的,至于在数据更新后要做什么事,全都由你来定,你可以依然是去调用某个对象的 setter 方法(别这么为难自己),也可以做其他的事,不管要做什么,都是要你自己来写的,ValueAnimator 不会帮你做。功能最少、最不方便,但有时也是束缚最少、最灵活。比如有的时候,你要给一个第三方控件做动画,你需要更新的那个属性没有 setter 方法,只能直接修改,这样的话 ObjectAnimator 就不灵了啊。怎么办?这个时候你就可以用 ValueAnimator,在它的 onUpdate() 里面更新这个属性的值,并且手动调用 invalidate()。
所以你看,ViewPropertyAnimator、ObjectAnimator、ValueAnimator 这三种 Animator,它们其实是一种递进的关系:从左到右依次变得更加难用,也更加灵活。但我要说明一下,它们的性能是一样的,因为 ViewPropertyAnimator 和 ObjectAnimator 的内部实现其实都是 ValueAnimator,ObjectAnimator 更是本来就是 ValueAnimator 的子类,它们三个的性能并没有差别。它们的差别只是使用的便捷性以及功能的灵活性。所以在实际使用时候的选择,只要遵循一个原则就行:尽量用简单的。能用 View.animate() 实现就不用 ObjectAnimator,能用 ObjectAnimator 就不用 ValueAnimator。

摘要:HenCoder Android 自定义 View 1-7:属性动画 Property Animation(进阶篇)相关推荐

  1. 【Android 属性动画】属性动画 Property Animation 与 视图动画 View Animation 区别

    文章目录 一.动画效果添加对象 二.动画效果类型 三.动画效果与实际属性 四.开发复杂程度 属性动画 Property Animation 可以为 任何对象 ( View 对象 / 非 View 对象 ...

  2. Android 属性动画Property Animation(中)

    Android 属性动画Property Animation(上)介绍了属性动画的概念以及相关的类和接口,本篇来看下具体肿么使用. ValueAnimator ValueAnimator指定整形.浮点 ...

  3. 属性动画-Property Animation之ViewPropertyAnimator 你应该知道的一切

    转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52381558 出自[zejian的博客] 关联文章: 走进绚烂多彩的 ...

  4. 走进绚烂多彩的属性动画-Property Animation(上篇)

    转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52273733 出自[zejian的博客] 关联文章: 走进绚烂多彩的 ...

  5. 走进绚烂多彩的属性动画-Property Animation之TimeInterpolator和TypeEvaluator(下篇)

    转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52334098 出自[zejian的博客] 关联文章: 走进绚烂多彩的 ...

  6. android 自定义 对号,Android自定义View实现打钩动画功能

    先上效果图 动图 静态图 1. 回顾 [Android自定义View:一个精致的打钩小动画]上一篇文章,我们已经实现了基本上实现了控件的效果了,但是...但是...过了三四天后,仔细看回自己写的代码, ...

  7. # HenCoder Android 自定义 View 1-8 硬件加速

    硬件加速这个词每当被提及,很多人都会感兴趣.这个词给大部分人的概念大致有两个:快速.不稳定.对很多人来说,硬件加速似乎是一个只可远观而不可亵玩的高端科技:是,我听说它很牛逼,但我不敢「乱」用,因为我怕 ...

  8. 这可能是第二好的自定义 View 教程之属性动画

    上期文章镇楼: 这可能是第二好的自定义 View 教程之绘制 凯哥的文章确实写的细而好呀,这不,活生生把 面试系列 先放一放,继续讲解我们的动画. 为啥是第二好? 一看就是没看 前面的文章 的.这里就 ...

  9. android显示绘图动画,Android自定义View绘图实现渐隐动画

    实现了一个有趣的小东西:使用自定义view绘图,一边画线,画出的线条渐渐变淡,直到消失.效果如下图所示: 用属性动画或者渐变填充(shader)可以做到一笔一笔的变化,但要想一笔渐变(手指不抬起边画边 ...

  10. Android 自定义View实现画背景和前景(ViewGroup篇)

    2019独角兽企业重金招聘Python工程师标准>>> 在定义ListView的Selector时候,有个drawSelectorOnTop的属性,如果drawSelectorOnT ...

最新文章

  1. 简单明了,一文入门视觉SLAM
  2. 苏宁Nodejs性能优化实战
  3. svm 程序matlab,求svm的matlab程序
  4. MySQL数据导入oracle
  5. ABAP:关于文本(Read_text,Save_text)
  6. php怎么添加会员卡,怎么在微信公众号中添加一个会员卡领取功能
  7. tomcat(2)一个简单的servlet容器
  8. JS函数调用的四种方法
  9. java类初始化_Java的类/实例初始化过程
  10. SAP License:SAP 更改背景图片
  11. 乔布斯首份手写求职信再次被拍卖
  12. c++ const常量的实现机制(转载)2
  13. VS2015 包含目录、库目录、附加包含目录、附加库目录、附加依赖项之详解
  14. java lambda有必要_深度分析:java8的新特性lambda和stream流,看完你学会了吗?
  15. IP地址的分类,五分类编制CIDR以及子网的划分和子网掩码
  16. 在浏览器上打开swf文件时变成了下载swf文件解决方式
  17. 基于Kotlin实现学生信息管理系统【100010063】
  18. dij与prim算法
  19. GIS+=地理信息+行业+大数据——纽约公开11亿条出租车和Uber原始数据下载及分析...
  20. 阿里面试应该注意什么?通过5轮面试的阿里实习生亲述

热门文章

  1. 算法题04:分治法:求第K小元素(线性时间选择算法)
  2. 视频编解码之H.264
  3. 使用ToStringBuilder.reflectionToString重写toString方法
  4. 用access建立一个试题库_access2010怎样建立自己的试题库?
  5. css 日语字体,css字体
  6. 雷达篇(四)雷达工作波段
  7. 域的基本管理:统一公司部门桌面
  8. 2022-Java面试宝典收藏版
  9. Druid-1.1.12.jar下载 (链接下载+使用)
  10. Silverlight实现文件的下载[很简单]