Android--Proper属性动画(二)

Property Animation动画有两个步聚:

1.计算属性值
2.为目标对象的属性设置属性值,即应用和刷新动画

1、首先了解TypeEvaluator的用法(告诉动画系统如何从初始值过度到结束值)

可能在大多数情况下我们使用属性动画的时候都不会用到TypeEvaluator,但是大家还是应该了解一下它的用法,以防止当我们遇到一些解决不掉的问题时能够想起来还有这样的一种解决方案。

ValueAnimator.ofFloat()方法就是实现了初始值与结束值之间的平滑过度,其实就是系统内置了一个FloatEvaluator,它通过计算告知动画系统如何从初始值过度到结束值

  1. public class FloatEvaluator implements TypeEvaluator {
  2. public Object evaluate(float fraction, Object startValue, Object endValue) {
  3. float startFloat = ((Number) startValue).floatValue();
  4. return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
  5. }
  6. }

可以看到,FloatEvaluator实现了TypeEvaluator接口,然后重写evaluate()方法。evaluate()方法当中传入了三个参数,

第一个参数fraction非常重要,这个参数用于表示动画的完成度的,我们应该根据它来计算当前动画的值应该是多少,

第二第三个参数分别表示动画的初始值和结束值。那么上述代码的逻辑就比较清晰了,用结束值减去初始值,算出它们之间的差值,然后乘以fraction这个系数,再加上初始值,那么就得到当前动画的值了。

好的,那FloatEvaluator是系统内置好的功能,并不需要我们自己去编写,但介绍它的实现方法是要为我们后面的功能铺路的。前面我们使用过了ValueAnimator的ofFloat()和ofInt()方法,分别用于对浮点型和整型的数据进行动画操作的,但实际上ValueAnimator中还有一个ofObject()方法,是用于对任意对象进行动画操作的。但是相比于浮点型或整型数据,对象的动画操作明显要更复杂一些,因为系统将完全无法知道如何从初始对象过度到结束对象,因此这个时候我们就需要实现一个自己的TypeEvaluator来告知系统如何进行过度。

  1. public class Point {
  2. private float x;
  3. private float y;
  4. public Point(float x, float y) {
  5. this.x = x;
  6. this.y = y;
  7. }
  8. public float getX() {
  9. return x;
  10. }
  11. public float getY() {
  12. return y;
  13. }
  14. }

Point类非常简单,只有x和y两个变量用于记录坐标的位置,并提供了构造方法来设置坐标,以及get方法来获取坐标。接下来定义PointEvaluator,如下所示:

如果想让动画生效,要同时满足两个条件:

1. object必须要提供setXxx方法,如果动画的时候没有传递初始值,那么还要提供getXxx方法,因为系统要去拿xxx属性的初始值(如果这条不满足,程序直接Crash)

2. object的setXxx对属性xxx所做的改变必须能够通过某种方法反映出来,比如会带来ui的改变啥的(如果这条不满足,动画无效果但不会Crash)

从源码可以看出,getWidth的确是获取View的宽度的,而setWidth是TextView和其子类的专属方法,它的作用不是设置View的宽度,而是设置TextView的最大宽度和最小宽度的,这个和TextView的宽度不是一个东西

具体来说,TextView的宽度对应Xml中的android:layout_width属性,而TextView还有一个属性android:width,这个android:width属性就对应了TextView的setWidth方法。

针对上述问题,Google告诉我们有3中解决方法:

1. 给你的对象加上get和set方法,如果你有权限的话

2. 用一个类来包装原始对象,间接为其提供get和set方法

3. 采用ValueAnimator,监听动画过程,自己实现属性的改变

1、给你的对象加上get和set方法,如果你有权限的话

这个的意思很好理解,如果你有权限的话,加上get和set就搞定了,但是很多时候我们没权限去这么做,比如本文开头所提到的问题,你无法给Button加上一个合乎要求的setWidth方法,因为这是Android SDK内部实现的。这个方法最简单,但是往往是不可行的,这里就不对其进行更多分析了。

2、用一个类来包装原始对象,间接为其提供get和set方法

这是一个很有用的解决方法,是我最喜欢用的,因为用起来很方便,也很好理解,下面将通过一个具体的例子来介绍它

  1. private void performAnimate() {
  2. ViewWrapper wrapper = new ViewWrapper(mButton);
  3. ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
  4. }
  5. @Override
  6. public void onClick(View v) {
  7. if (v == mButton) {
  8. performAnimate();
  9. }
  10. }
  11. private static class ViewWrapper {
  12. private View mTarget;
  13. public ViewWrapper(View target) {
  14. mTarget = target;
  15. }
  16. public int getWidth() {
  17. return mTarget.getLayoutParams().width;
  18. }
  19. public void setWidth(int width) {
  20. mTarget.getLayoutParams().width = width;
  21. mTarget.requestLayout();
  22. }
  23. }

3、采用ValueAnimator,监听动画过程,自己实现属性的改变

首先说说啥是ValueAnimator,ValueAnimator本身不作用于任何对象,也就是说直接使用它没有任何动画效果。它可以对一个值做动画,然后我们可以监听其动画过程,在动画过程中修改我们的对象的属性值,这样也就相当于我们的对象做了动画。

  1. private void performAnimate(final View target, final int start, final int end) {
  2. ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
  3. valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
  4. //持有一个IntEvaluator对象,方便下面估值的时候使用
  5. private IntEvaluator mEvaluator = new IntEvaluator();
  6.       每一帧都会回调这个方法
  7. @Override
  8. public void onAnimationUpdate(ValueAnimator animator) {
  9. //获得当前动画的进度值,整型,1-100之间
  10. int currentValue = (Integer)animator.getAnimatedValue();
  11. Log.d(TAG, "current value: " + currentValue);
  12. //计算当前进度占整个动画过程的比例,浮点型,0-1之间
  13. float fraction = currentValue / 100f;
  14. //这里我偷懒了,不过有现成的干吗不用呢
  15. //直接调用整型估值器通过比例计算出宽度,然后再设给Button
  16. target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
  17. target.requestLayout();
  18. }
  19. });
  20. valueAnimator.setDuration(5000).start();
  21. }
  22. @Override
  23. public void onClick(View v) {
  24. if (v == mButton) {
  25. performAnimate(mButton, mButton.getWidth(), 500);
  26. }
  27. }

上述代码的动画效果图和采用ViewWrapper是一样的,请参看上图。关于这个ValueAnimator我要再说一下,拿上例来说,它会在5000ms内将一个数从1变到100,然后动画的每一帧会回调onAnimationUpdate方法,在这个方法里,我们可以获取当前的值(1-100),根据当前值所占的比例(当前值/100),我们可以计算出Button现在的宽度应该是多少,比如时间过了一半,当前值是50,比例为0.5,假设Button的起始宽度是100px,最终宽度是500px,那么Button增加的宽度也应该占总增加宽度的一半,总增加宽度是500-100=400,所以这个时候Button应该增加宽度400*0.5=200,那么当前Button的宽度应该为初始宽度+ 增加宽度(100+200=300)。上述计算过程很简单,其实它就是整型估值器IntEvaluator的内部实现,所有我们不用自己写了,直接用吧。

  • Duration:动画的持续时间,单位ms
  • TimeInterpolation:属性值的计算方式,如先快后慢,是一个接口。用来设置插值器
  • TypeEvaluator(估值器):根据属性的开始、结束值与TimeInterpolation计计算出“当前”时间的属性值,这个值可以在AnimationUpdate中得到
  • Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
  • Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
  • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响
时间: 2024-10-10 01:09:35

Android--Proper属性动画(二)的相关文章

Android之属性动画(二)

上一篇文章(链接:http://blog.csdn.net/jerehedu/article/details/45305683 ),我们对属性动画有了简单的认识,并实际动手使用ObjectAnimator.AnimatorSet完了一个简单的例子,本次继续对剩余内容进行学习. 首先让我们先来了解一下动画是如何计算的呢?从官方文档上我们可以看到下面这张图: 图中描述了动画过程中相互工作的主要类,其中ValueAnimator对象可以记录动画时间轨迹.ValueAnimator中含有一个TimeIn

Android之属性动画(一)

一.概述 Android平台中常用的动画主要有两类,一类是View动画,一类是3.0后新增的属性动画.属性动画与View动画相比功能更加强大,主要体现在以下两个方面: 1.  属性动画不仅仅能应用到View上,还可以应用到Object对象上. 2.  属性动画将会真正改变Object对象属性的值. 如此强大的动画,我们没有理由不去学习使用,下面我们就根据API文档的介绍开始学习如何使用属性动画. 二.属性动画的学习与使用 首先我们要先了解属性动画的一些关键属性,文档中给出了这么几个: Durat

android之属性动画和布局动画详解

1.属性动画是什么不废话,不懂的可以百度一下参考郭霖大神的动画详解篇:这里仅仅提供一个demo说说用法,抛砖引玉,代码的注释写的已经很详细,不再多说废话,一下提供的是一个基础的demo,讲解的是objectAnimator的基础用法,如平移.旋转.缩放.渐变以及动画的集合:至于objectAnimator(必须的有set get方法)和valueAnimator的详细区别也可参考郭霖大神的动画详解篇 2.除此基本用法,还有估值器和插值器 (1)插值器:动画速率的变换,有点类似物理的加速度,就是该

Android进阶——属性动画Property Animation详解(一)

引言 前一篇文章Android入门--补间动画和帧动画应用小结总结了补间动画和帧动画及一些相关类的应用,基本可以掌握简单的缩放.旋转.透明度变化.平移的动画效果,但是需要实现更复杂的动画效果时,比如说希望View的切换动画.Layout的切换动画.3D旋转动画等等,这些View Animation都无法做到.此时Property Animation应运而生,这篇主要总结下属性动画的相关知识点. 一.Property Animation属性动画概述 属性动画,在我最先接触到Android 1.5时

Android:属性动画详解

(一)简介 属性动画是Android 3.0中提供了新功能,便于对任意元素进行"平滑的过渡".众所周知,Android 之前提供的补间动画如AlphaAnimation.TranslateAnimation等都只能应用在View上,并且几乎没有任何可扩展的地方.并且,使用原来的动画无法实现颜色渐变效果,算是一个遗憾. 属性动画彻底打破了这种设计方式,不再将这些动画强制的放在View上,而是仅仅产生一系列的值,由开发人员自行使用这些值.例如,属性动画可产生1-0平滑过渡的值,把这些值应用

android学习(属性动画扇形菜单栏)

1 public class TestActivity extends Activity implements OnClickListener{ 2 private int[] res={R.id.imageView1,R.id.imageView2,R.id.imageView3,R.id.imageView4,R.id.imageView5,R.id.imageView6}; 3 private List<ImageView> list=new ArrayList<ImageView

android的属性动画

原文作者:Google 原文地址:https://developer.android.com/guide/topics/graphics/prop-animation.html 原文版权:Creative Commons 2.5 Attribution License 译文作者:Jianan - [email protected] 版本信息:本文基于2016-06-17版本翻译 译文版权:CC BY-NC-ND 4.0,允许复制转载,但必须保留译文作者署名及译文链接,不得演绎和用于商业用途 前言

Android用属性动画拖动view到任意位置

直接上图: 代码: package me.waye; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageVie

Android之属性动画、值动画

Android属性动画 什么是Android属性动画 同类技术对比 补间动画Tween Animation 帧动画Frame Animation 属性动画Property Animation 属性动画组成部分相关类介绍 ObjectAnimator对象动画执行类 介绍 示例 ValueAnimator 值动画执行类 介绍 示例 PropertyValuesHolder 属性存储器 介绍 示例 Keyframe 关键帧 介绍 示例 AnimatorSet 执行集合类 介绍 示例 AnimatorU

Android中属性动画的基本用法

在开发中属性动画是很常用的功能,下面我把属性动画的基本用法记录一下,供他人学习,也逐渐积累自己的知识. 单个动画效果: //创建动画对象,后面的参数依次为:动画效果的目标组件,需要改变的该组建的属性(必须有对应的get和set方法就可以),后面三个参数写变化过程对应数值. ObjectAnimator animator= ObjectAnimator.ofFloat(textView, "TextSize", 15, 50, 15); //动画过程所用时间,会按这个世界自动平滑执行 a