Android动画

Android动画分为三类

1、补间动画


Tween Animation(补间动画):

    Tween动画,通过对View的内容进行一系列的图形变换 (包括平移、缩放、旋转、改变透明度)来实现动画效果。动画效果的定义可以采用XML来做也可以采用编码来做。


动画类型XML配置方式Java代码实现方式

渐变透明度动画效果AlphaAnimation

渐变尺寸缩放动画效果ScaleAnimation

画面旋转动画效果RotateAnimation

画面位置移动动画效果TranslateAnimation

组合动画效果AnimationSet

xml文件存放目录如下图所示:

具体如何实现:

1.)alpha渐变透明度动画效果

xml方式:

fromAlpha:开始时透明度

toAlpha: 结束时透明度

duration:动画持续时间

fillAfter:设置动画结束后保持当前的位置

XML方式加载方式通过AnimationUtils.loadAnimation(this, R.anim.anim_alpha)获取Animation

Animation alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_alpha);

  imageView.startAnimation(alphaAnimation);

Java代码方式:

Animation alphaAnimation =newAlphaAnimation(1.0f, 0.0f);

  alphaAnimation.setDuration(500);//设置动画持续时间为500毫秒alphaAnimation.setFillAfter(false);//设置动画结束后保持当前的位置(即不返回到动画开始前的位置)imageView.startAnimation(alphaAnimation);

2.)scale渐变尺寸缩放动画效果

xml方式:

fromXDelta,fromYDelta 起始时X,Y座标,屏幕右下角的座标是X:320,Y:480

toXDelta, toYDelta    动画结束时X,Y的座标

interpolator            指定动画插入器

fromXScale,fromYScale, 动画开始前X,Y的缩放,0.0为不显示,  1.0为正常大小

toXScale,toYScale,    动画最终缩放的倍数, 1.0为正常大小,大于1.0放大

pivotX,  pivotY        动画起始位置,相对于屏幕的百分比,两个都为50%表示动画从自身中间开始

startOffset,          动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,单位毫秒

duration,一次动画效果消耗的时间,单位毫秒,值越小动画速度越快

repeatCount,动画重复的计数,动画将会执行该值+1次

repeatMode,动画重复的模式,reverse为反向,当第偶次执行时,动画方向会相反。restart为重新执行,方向不变

Java方式:

Animation scaleAnimation =newScaleAnimation(0.0f, 1.5f, 0.0f, 1.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

    scaleAnimation.setDuration(500);//设置动画持续时间为500毫秒scaleAnimation.setFillAfter(true);//如果fillAfter的值为true,则动画执行后,控件将停留在执行结束的状态scaleAnimation.setFillBefore(false);//如果fillBefore的值为true,则动画执行后,控件将回到动画执行之前的状态scaleAnimation.setRepeatCount(3);//设置动画循环次数    scaleAnimation.setRepeatMode(Animation.REVERSE);

    scaleAnimation.setStartOffset(0);

    scaleAnimation.setInterpolator(this, android.R.anim.decelerate_interpolator);//设置动画插入器imageView.startAnimation(scaleAnimation);

3.)rotate画面旋转动画效果

xml方式:

fromDegrees 动画开始时的角度

toDegrees    动画结束时物件的旋转角度,正代表顺时针

pivotX    属性为动画相对于物件的X坐标的开始位置

pivotY    属性为动画相对于物件的Y坐标的开始位置

Java方式:

Animation rotateAnimation =newRotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

rotateAnimation.setDuration(500);

rotateAnimation.setFillAfter(true);

rotateAnimation.setInterpolator(this, android.R.anim.accelerate_decelerate_interpolator);//设置动画插入器imageView.startAnimation(rotateAnimation);

4.)translate画面位置移动动画效果

xml方式:

fromXDelta,fromYDelta 起始时X,Y座标,屏幕右下角的座标是X:320,Y:480

toXDelta, toYDelta    动画结束时X,Y的座标

Java方式

Animation translateAnimation =newTranslateAnimation(0, 100, 0, 0);

translateAnimation.setDuration(500);

translateAnimation.setInterpolator(this, android.R.anim.cycle_interpolator);//设置动画插入器translateAnimation.setFillAfter(true);//设置动画结束后保持当前的位置(即不返回到动画开始前的位置)imageView.startAnimation(translateAnimation);

5.)set组合动画效果

xml方式:

        android:duration="500"        android:fromAlpha="1.0"        android:toAlpha="0.0"/>

        android:duration="500"        android:fromXScale="0.0"        android:fromYScale="0.0"        android:interpolator="@android:anim/decelerate_interpolator"        android:pivotX="50%"        android:pivotY="50%"        android:repeatCount="1"        android:repeatMode="reverse"        android:startOffset="0"        android:toXScale="1.5"        android:toYScale="1.5"/>

如何使用

AnimationSet animationSet = (AnimationSet) AnimationUtils.loadAnimation(this, R.anim.anim_set);

  imageView.startAnimation(animationSet);

Java方式

AnimationSet animationSet =newAnimationSet(true);

Animation alphaAnimation =newAlphaAnimation(1.0f, 0.1f);

alphaAnimation.setDuration(500);//设置动画持续时间为500毫秒Animation scaleAnimation =newScaleAnimation(0.0f, 1.5f, 0.0f, 1.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

scaleAnimation.setDuration(500);//设置动画持续时间为500毫秒scaleAnimation.setRepeatMode(Animation.REVERSE);

scaleAnimation.setStartOffset(0);

scaleAnimation.setInterpolator(this, android.R.anim.decelerate_interpolator);//设置动画插入器animationSet.addAnimation(alphaAnimation);

animationSet.addAnimation(scaleAnimation);

imageView.startAnimation(animationSet);

动画监听器Animation.AnimationListener:

 有时可能我们要在动画的每个周期里面做不同的操作,这时候就要借助动画监听器了

alphaAnimation.setAnimationListener(new Animation.AnimationListener() {

    @Override

    publicvoid onAnimationStart(Animation animation) {

        //动画开始时调用    }

    @Override

    publicvoid onAnimationEnd(Animation animation) {

        //动画结束时调用    }

    @Override

    publicvoid onAnimationRepeat(Animation animation) {

        //动画重复时调用    }

    });


几种自带的动画插入器

AccelerateInterpolator 加速,开始时慢中间加速

DecelerateInterpolator 减速,开始时快然后减速

AccelerateDecelerateInterolator 先加速后减速,开始结束时慢,中间加速

AnticipateInterpolator 反向,先向相反方向改变一段再加速播放

AnticipateOvershootInterpolator 反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值

BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100

CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input)

LinearInterpolator 线性,线性均匀改变

OvershootInterpolator超越,最后超出目的值然后缓慢改变到目的值



2、帧动画

Frame animation

其实就是多张图片构成的gif图片

在drawable文件下创建animation-list文件

如下

代码中使用AnimationDrawable

AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();

animationDrawable.start();

animationDrawable.stop();//停止动画

3、java代码实现:

AnimationDrawable anim =newAnimationDrawable();for (int i = 1; i <= 6; i++) {int id = getResources().getIdentifier("lottery_" + i, "mipmap", getPackageName()); Drawable drawable =getResources().getDrawable(id); anim.addFrame(drawable, 200); } anim.setOneShot(false);

    imageView.setImageDrawable(anim);

    anim.start();

4.AnimationDrawable 几个常见的api

void start()- 开始播放动画

void stop()- 停止播放动画

addFrame(Drawable frame, int duration)- 添加一帧,并设置该帧显示的持续时间

void setOneShoe(boolean flag)- false为循环播放,true为仅播放一次

boolean isRunning()- 是否正在播放


3、属性动画

Property Animation相关类

   属性动画,根据字面理解可以通过修改物件的属性值以达到动画效果。

类名用途

ValueAnimator属性动画主要的计时器,也计算动画后的属性的值,动画的执行类

ObjectAnimator  ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画,动画的执行类

AnimatorSet提供组织动画的结构,使它们能相关联得运行,用于控制一组动画的执行

AnimatorInflater 用户加载属性动画的xml文件

Evaluators 属性动画计算器,告诉了属性动画系统如何计算给出属性的值

Interpolators动画插入器,定义动画的变化率

 上面几个重要类之间的关系如下图所示:


今天先通过最简单最容易理解的ObjectAnimator来学习总结。

ObjectAnimator:

   ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画。当这个类计算好一个动画的新值后,相应的会更新其属性。大多数时候你都会想用ObjectAnimator,因为它使得动画值到目标对象的处理更简单了。

1.)以实现一个View透明渐变效果为例进行说明

xml实现方式:

这里需要注意是的属性动画文件存放目录为res/animator

need-to-insert-img

duration 表示动画执行的时间

propertyName 表示修改的物件的哪个属性值,这里是透明度

valueFrom 表示从哪个状态值开始动画

valueTo 表示到哪个状态值结束动画

valueType 类型估值,主要用于设置动画操作属性的值

repeatMode 表示重复的模式 reverse表示

repeatCount 动画重复的计数,动画将会执行该值+1次

repeatMode 动画重复的模式,reverse为反向,当第偶次执行时,动画方向会相反。restart为重新执行,方向不变

startOffset, 动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,单位毫秒 

interpolator 指定动画插入器

通过上面的xml属性可以看出和补间动画基本上一致,然后通过AnimatorInflater 来加载xml中的动画

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_alpha);

anim.setTarget(imageView);

anim.start();

当然也可以通过纯Java代码的方式实现

need-to-insert-img

ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);

    alphaAnimation.setDuration(500);

    alphaAnimation.setRepeatCount(0);

    alphaAnimation.setRepeatMode(ValueAnimator.REVERSE);

    alphaAnimation.setStartDelay(200);

    alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());

    alphaAnimation.start();

need-to-insert-img

对于java代码实现,ObjectAnimator

提供了以下几个方法:ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。

其他举例:

缩放动画:

xml:

need-to-insert-img

need-to-insert-img

java代码:

ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);

  scaleXAnimator.setDuration(500);

  scaleXAnimator.setRepeatCount(1);

  scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE);

  scaleXAnimator.start();

旋转动画:

 xml:

need-to-insert-img

need-to-insert-img

java代码:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);

    objectAnimator.setDuration(500);

    objectAnimator.setRepeatCount(1);

    objectAnimator.setRepeatMode(ValueAnimator.REVERSE);

    objectAnimator.start();

平移动画:

xml:

need-to-insert-img

need-to-insert-img

java代码:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 100f);

    objectAnimator.setDuration(500);

    objectAnimator.setRepeatCount(1);

    objectAnimator.setRepeatMode(ValueAnimator.REVERSE);

    objectAnimator.start();

2.)如何实现一个组合动画

    举例我们同时对一个控件进行宽高两个维度的缩放

方式一:使用AnimatorSet

need-to-insert-img

        android:duration="500"        android:propertyName="scaleX"        android:repeatCount="1"        android:repeatMode="reverse"        android:valueFrom="1.0"        android:valueTo="1.5"        android:valueType="floatType"/>

        android:duration="500"        android:propertyName="scaleY"        android:repeatCount="1"        android:repeatMode="reverse"        android:valueFrom="1.0"        android:valueTo="1.5"        android:valueType="floatType"/>

need-to-insert-img

加载xml动画

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_scale);

      anim.setTarget(imageView);

      anim.start();

纯Java代码实现:

need-to-insert-img

AnimatorSet animatorSet =new AnimatorSet();

    ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);

    scaleXAnimator.setDuration(500);

    scaleXAnimator.setRepeatCount(1);

    scaleXAnimator.setRepeatMode(ValueAnimator.REVERSE);

    scaleXAnimator.start();

    ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 1.5f);

    scaleYAnimator.setDuration(500);

    scaleYAnimator.setRepeatCount(1);

    scaleYAnimator.setRepeatMode(ValueAnimator.REVERSE);

    animatorSet.playTogether(scaleXAnimator, scaleYAnimator);

    animatorSet.start();

need-to-insert-img

上述代码通过playTogether函数实现两个动画同时执行,如果不想同时执行,也可以调用play函数返回AnimatorSet.Builder实例,AnimatorSet.Builder提供了如下几个函数用于实现动画组合:

after(Animator anim) 将现有动画插入到传入的动画之后执行

after(long delay) 将现有动画延迟指定毫秒后执行

before(Animator anim) 将现有动画插入到传入的动画之前执行

with(Animator anim) 将现有动画和传入的动画同时执行

也可以调用playSequentially函数实现分布执行动画。

方式二:使用PropertyValuesHolder

need-to-insert-img

PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);

PropertyValuesHolder scaleYValuesHolder = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f);

ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, scaleXValuesHolder, scaleYValuesHolder);

    objectAnimator.setDuration(500);

    objectAnimator.setRepeatCount(1);

    objectAnimator.setRepeatMode(ValueAnimator.REVERSE);

    objectAnimator.start();

need-to-insert-img

通过这种方式只能实现同时执行的动画组合相比AnimatorSet就没那么丰富了,PropertyValuesHolder 提供的函数方法有如下几种:ofInt()、ofFloat()、ofObject()、ofKeyframe()。

方式三:使用ViewPropertyAnimator

ViewPropertyAnimator viewPropertyAnimator=imageView.animate();

viewPropertyAnimator.scaleXBy(1.0f).scaleX(1.5f).scaleYBy(1.0f).scaleY(1.5f).setDuration(500).start();

多属性动画,作用于View,能够实现的动画相对单一,只能实现比如缩放,透明度改变,平移、旋转等,具体函数名字:平移 translationX,translationY, X,Y,缩放 scaleX,scaleY, 旋转 rotationX, rotationY,透明度 alpha

3.)设置动画监听器

有时候我们可能要在某一个动画执行之前 或者动画结束之后进行一些其他的操作,这个时候就要借助动画监听器了。

need-to-insert-img

objectAnimator.addListener(new Animator.AnimatorListener() {

    @Override

    publicvoid onAnimationStart(Animator animation) {

        //TODO 动画开始前的操作    }

    @Override

    publicvoid onAnimationEnd(Animator animation) {

        //TODO 动画结束的操作    }

    @Override

    publicvoid onAnimationCancel(Animator animation) {

      //TODO 动画取消的操作    }

    @Override

    publicvoid onAnimationRepeat(Animator animation) {

        //TODO 动画重复的操作    }

    });

need-to-insert-img

如果我们需要简单动画执行过程中的变化可以使用AnimatorUpdateListener

need-to-insert-img

objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override

    publicvoid onAnimationUpdate(ValueAnimator animation) {

        floatvalue = (float) animation.getAnimatedValue();

        //可以根据自己的需要来获取动画更新值。Log.e("AnimatorUpdateListener", "the animation value is " + value);

    }

    });

前面初步认识了Android的Property Animation(属性动画)Android动画效果之初识Property Animation(属性动画)(三),并且利用属性动画简单了补间动画能够实现的动画效果,今天重点学习下Property Animation基本原理及高级使用。本章先通过余额宝的数字动画小例子来学习属性动画基本原理。具体效果如下:

ValueAnimator(差值动画)


上篇文章一直使用的ObjectAnimator来实现属性动画,单纯从字面上理解的话ObjectAnimator作用于某个实际的对象,而ValueAnimator是ObjectAnimator的父类,它继承自抽象类Animator,它作用于一个值,将其由一个值变化为另外一个值,然后根据值的变化,按照一定的规则,动态修改View的属性,比如View的位置、透明度、旋转角度、大小等,即可完成了动画的效果。直接看下上面的数字动画是怎么实现的?

ValueAnimator valueAnimator =ValueAnimator.ofFloat( 0f, 126512.36f);

valueAnimator.setDuration(2000);

valueAnimator.setInterpolator(new LinearInterpolator());

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override

    publicvoid onAnimationUpdate(ValueAnimator animation) {

    floatmoney= (float) animation.getAnimatedValue();

    mTextView.setText(String.format("%.2f", money));

    }

});

valueAnimator.start();

这里通过ofFloat()方法构造一个ValueAnimator实例,除此之外还提供了其他函数ofInt()、ofObject()、ofPropertyValuesHolder()函数,api

21之后又提供了ofArgb(),每个函数都是可以传入多个改变值。

Interpolator(插值器)

   Interpolator插值器用于控制动画的变化速率,也可以简单的理解成用于控制动画的快慢,插值器目前都只是对动画执行过程的时间进行修饰,并没有对轨迹进行修饰。系统提供的插值器有以下几种:

插值器名字解说对应的xml

AccelerateInterpolator 加速,开始时慢中间加速 @android:anim/accelerate_interpolator

DecelerateInterpolator减速,开始时快然后减速@android:anim/decelerate_interpolator

AccelerateDecelerateInterolator  先加速后减速,开始结束时慢,中间加速 @android:anim/accelerate_decelerate_interpolator

AnticipateInterpolator反向 ,先向相反方向改变一段再加速播放 @android:anim/anticipate_interpolator

AnticipateOvershootInterpolator反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值@android:anim/anticipate_overshoot_interpolator

BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100@android:anim/bounce_interpolator

CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input)@android:anim/cycle_interpolator

LinearInterpolator 线性,线性均匀改变@android:anim/linear_interpolator

OvershootInterpolator超越,最后超出目的值然后缓慢改变到目的值@android:anim/overshoot_interpolator

通过上面的名字大家是不是很眼熟,是的和补间动画的插值器是一致的。Android的动画插值器采用策略设计模式,都是实现了Interpolator这个接口,而Interpolator又是继承自一个叫做TimeInterpolator的接口(从3.0开始,增加了TimeInterpolator这个接口,并把原先的Interpolator接口的抽象方法移到了其中,3.0后的Interpolator接口也就什么也没做,只是对父类改了个名字,达到向下兼容)。

package android.animation;publicinterface TimeInterpolator {

    floatgetInterpolation(float input);

}

在Interpolator的实现类里面,都实现了一个float getInterpolator(float

input)的方法,传入参数是正常执行动画的时间点,返回值是用户真正想要它执行的时间点。上面的数字动画使用了匀速插值器LinearInterpolator其代码实现如下:

publicclassLinearInterpolatorextendsBaseInterpolatorimplements NativeInterpolatorFactory {

    public LinearInterpolator() {

    }

    public LinearInterpolator(Context context, AttributeSet attrs) {

    }

    publicfloatgetInterpolation(float input) {

        return input;

    }

    /** @hide */    @Override

    publiclong createNativeInterpolator() {

        return NativeInterpolatorFactoryHelper.createLinearInterpolator();

    }

}

可以看出float getInterpolator(float input)返回的值就是当前要执行的时间点实现匀速执行动画。

如何自定义一个插值器?举例:我们实现一个先减速后加速插值器,代码如下

publicclassDecelerateAccelerateInterpolatorimplements Interpolator {

    @Override

    publicfloatgetInterpolation(float input) {

        float result;

        if(input <= 0.5f) {

            result = (float) (Math.sin(Math.PI * input)) / 2.0f;

        } else {

            result = (float) (2 - Math.sin(Math.PI * input)) / 2.0f;

        }

        return result;

    }

}

TypeEvaluator(估值器)

  TypeEvaluator用于根据当前属性改变的百分比来计算改变后的属性值,系统提供了如下几种估值器

IntEvaluator 针对整型属性

IntArrayEvaluator 针对整型属性集合

FloatEvaluator 针对浮点型属性

FloatArrayEvaluator 针对浮点型属性集合

ArgbEvaluator  针对Color属性

RectEvaluator 针对Rect属性

PointFEvaluator 针对PointF属性

  TypeEvaluator设计也是采用策略设计模式,都实现TypeEvaluator接口,源代码如下:

package android.animation;publicinterfaceTypeEvaluator {

    publicT evaluate(float fraction, T startValue, T endValue);

}

接口提供了evaluate(float fraction, T startValue, T

endValue);动画在运行过程中Interpolator自动计算出动画运行的百分比fraction,然后TypeEvaluator根据fraction计算出当前动画的属性值。以FloatEvaluator

代码为例:

publicclassFloatEvaluatorimplementsTypeEvaluator {

    publicFloat evaluate(float fraction, Number startValue, Number endValue) {

        floatstartFloat = startValue.floatValue();

        returnstartFloat + fraction * (endValue.floatValue() - startFloat);

    }

}

 如何自定义TypeEvaLuator?比如我们要实现一个钱的增加,字体颜色越红的动画,我们现在都知道可以使用ofArgb(),但是ofArgb()需要api

21以上才能使用,所以需要我们自定义一个ArgbEvaLuator,这里为了演示自定义TypeEvaluator直接把api

21中提供的ArgbEvaluator源代码拿来使用,如下:

publicclassTextArgbEvaluatorimplements TypeEvaluator {


    publicObject evaluate(float fraction, Object startValue, Object endValue) {

        intstartInt = (Integer) startValue;

        intstartA = (startInt >> 24) & 0xff;

        intstartR = (startInt >> 16) & 0xff;

        intstartG = (startInt >> 8) & 0xff;

        intstartB = startInt & 0xff;

        intendInt = (Integer) endValue;

        intendA = (endInt >> 24) & 0xff;

        intendR = (endInt >> 16) & 0xff;

        intendG = (endInt >> 8) & 0xff;

        intendB = endInt & 0xff;

        return(int) ((startA + (int) (fraction * (endA - startA))) << 24) |                (int) ((startR + (int) (fraction * (endR - startR))) << 16) |                (int) ((startG + (int) (fraction * (endG - startG))) << 8) |                (int) ((startB + (int) (fraction * (endB - startB))));

    }

}

调用方式:

AnimatorSet animatorSet =new AnimatorSet();

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 126512.36f);

        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override

            publicvoid onAnimationUpdate(ValueAnimator animation) {

                floatmoney = (float) animation.getAnimatedValue();

                Log.e("Interpolator", "money---->" + money);

                mTextView.setText(String.format("%.2f", money));

            }

        });

        intstartColor = Color.parseColor("#FCA3AB");

        intendColor = Color.parseColor("#FB0435");

        ValueAnimator colorAnimator = ValueAnimator.ofObject(new TextArgbEvaluator(),startColor, endColor);

        colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override

            publicvoid onAnimationUpdate(ValueAnimator animation) {

                intcolor = (int) animation.getAnimatedValue();

                Log.e("Interpolator", "color---->" + color);

                mTextView.setTextColor(color);

            }

        });

        animatorSet.playTogether(valueAnimator,colorAnimator);

        animatorSet.setDuration(5000);

        animatorSet.setInterpolator(new LinearInterpolator());

        animatorSet.start();

运行效果:

ObjectAnimator


上篇我们简单了学习了ObjectAnimator动画,并且通过ObjectAnimator实现了几种简单的动画效果,ObjectAnimator继承自ValueAnimator,所以主体方法还是ValueAnimator里实现的。先来回顾一下上篇的一个旋转动画例子。

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);

    objectAnimator.setDuration(500);

    objectAnimator.setRepeatCount(1);

    objectAnimator.setRepeatMode(ValueAnimator.REVERSE);

    objectAnimator.start();

这个例子很简单,针对view的属性rotation进行持续时间为500ms的0到360的角度变换。属性名字rotation在View中有对应setRotation(),否则没有任何效果,而且参数类型必须为float型,否则没有任何效果。view常见可操作的参数有:x/y;scaleX/scaleY;rotationX/

rotationY;transitionX/ transitionY等等。现在问题来了,我们本篇例子是为TextView

赋值一个float型的值,我们查看TextView的函数并不找不到setText(float

f),这时该怎么处理呢?如何为不具有get/set方法的属性提供修改方法呢?莫着急!谷歌为此提供了两种方法,第一种就是使用ValueAnimator来实现,就是上面所说的方式,另外一种方式通过自己写一个包装类,来为该属性提供get/set方法。

publicclassMoneyTextViewextends TextView {

    public MoneyTextView(Context context, AttributeSet attrs) {

        super(context, attrs);

    }

    publicvoidsetText(float money) {

        setText(String.format("%.2f", money));

    }

}

然后就可以通过ObjectAnimator实现上面的数字动画效果了。

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "text", 0f, 126512.36f);

    objectAnimator.setDuration(2000);

    objectAnimator.setInterpolator(new LinearInterpolator());

    objectAnimator.start();

你可能感兴趣的:(Android动画)