美文网首页
Android属性动画使用指南

Android属性动画使用指南

作者: Cris_Ma | 来源:发表于2017-05-14 00:15 被阅读0次

属性动画的分类

ValueAnimator

ValueAnimator是整个属性动画机制当中最核心的一个类,它通过我们给定的初始值,结束值和动画时间,内部计算出动画过程,从而完成平滑的移动效果。另外,它还管理动画的播放次数,模式以及设置监听等功能。
它是最基础的核心类,并不能直接操作View,他操作的是值,操作的对象通常也是对值进行包装的对象。但是,我们可以根据这些值的变化来实现View的动画效果。

常用方法:

ValueAnimator.ofFloat/ofint 设置初始值和结束值 ,可以传入多个参数,运行时依次变化到最后一个值
setDuration() 设置动画时间
addUpdateListener 为动画设置监听,可以随时获取动画的当前状态
setStartDelay() 设置动画延时
setRepeatCount()/Mode() 设置重复次数,重复模式(RESTART,REVERSE)

ValueAnimator实现动画效果
除了上边的方法之外,ValueAnimator还有一个稍微复杂的ofObject()方法,用来操作对象,可以用它来实现视图的动画效果。它接收三个参数,除了初始值和结束值之外,它还需要一个TypeEvaluator。

TypeEvaluator是一个用来计算滑动过程的接口,查看一下ofFloat/ofint,他们内部也实现了这个接口,我们操作对象的时候,需要自己定义计算方法,他有三个参数,第一个表示完成度,后两个表示初始和结束值。

下面用一个例子来演示一下ValueAnimator是如何操作View的。
首先定义一个class,用来存储Value(x,y方法的坐标值),View的移动通过改变坐标来实现。

public class Cordinate {
    private float x;
    private float y;
    public Cordinate(float x, float y) {        
        this.x = x;
        this.y = y;
    }
    public float getX() {
        return x;
    }
    public float getY() {
        return y;
    }
}

然后自定义一个View,用来实现一个圆形的移动效果:

public class ValueAnimatorDemoView extends View{
    private Paint mPaint;
    private Cordinate curCordinate;
    public ValueAnimatorDemoView(Context context) {
        this(context,null);
        // TODO Auto-generated constructor stub
    }
    public ValueAnimatorDemoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
    }
      @Override  
        protected void onDraw(Canvas canvas) {  
            if (curCordinate == null) {  
                curCordinate = new Cordinate(50 , 50);  
                drawCircle(canvas);  
                startAnimation();  
            } else {  
                drawCircle(canvas);  
            }  
        }  
        private void drawCircle(Canvas canvas) {  
            float x = curCordinate.getX();  
            float y = curCordinate.getY();  
            canvas.drawCircle(x, y, 50, mPaint);  
        }  
        private void startAnimation() {  
            Cordinate startPoint = new Cordinate(50, 50);  
            Cordinate endPoint = new Cordinate(getWidth() - 50, getHeight() - 50);  
            ValueAnimator anim = ValueAnimator.ofObject(new MyEvalutor(), startPoint, endPoint);  
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
                @Override  
                public void onAnimationUpdate(ValueAnimator animation) {  
                    curCordinate = (Cordinate) animation.getAnimatedValue();  
                    invalidate();  
                }  
            });  
            anim.setDuration(5000);  
            anim.start();  
        }  
        private class MyEvalutor implements TypeEvaluator<Cordinate>{
            @Override
            public Cordinate evaluate(float fraction, Cordinate startValue,
                    Cordinate endValue) {
                // TODO Auto-generated method stub
                Cordinate startPoint = (Cordinate) startValue;
                Cordinate endPoint = (Cordinate) endValue;
                float x = startPoint.getX() + fraction*(endPoint.getX() -startPoint.getX() );
                float y = startPoint.getY() + fraction*(endPoint.getY() -startPoint.getY() );
                Cordinate curpoint = new Cordinate(x,y);
                return curpoint;
            }
        }
}

在onDraw方法中,先进行判断,如果curCordinate对象为null,说明是第一次运行,新建一个坐标Cordinate对象,初始值为50,50,用来在屏幕的X/Y坐标为50,50的地方(左上角),绘制一个圆形,半径为50。

绘制完成后,开始动画,第一步定义初始和结束位置,分别是左上角和右下角,然后开始运行动画。需要注意的是这里添加了UpdateListener用来实时监听当前坐标值,然后invalidate,根据当前坐标绘制圆形,而当前坐标又是通过MyEvalutor 方法来计算出的,是一系列逐步变化的值,通过这些值来绘制View就完成了整个动画效果。

ObjectAnimator

ObjectAnimator继承自ValueAnimator,它可以对View的各项属性进行操作。
例如将一个View从常规变换成全透明,再从全透明变换成常规,就可以这样写:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
animator.setDuration(5000);  
animator.start();  

再看一个变化背景颜色的例子:

ValueAnimator colorAnim = ObjectAnimator.ofInt(mButton,"backgroundColor", 0xFFFF8080, 0xFF8080FF);
            colorAnim.setDuration(5000);
            colorAnim.setEvaluator(new ArgbEvaluator());
            colorAnim.start();

这里用来系统的ArgbEvaluator来进行颜色变化的计算,当然我们也可以自己定义变化方法。另外需要注意的是第二个属性,它的原理是查找所操作的对象中对应的setXXX和getXXX方法,XXX就是我们填入的参数。常用的参数有这些:

rotation, rotationX/Y, translationX/Y, scaleX/Y, alpha,color, backgroundColor等等

除此之外,我们也可以自己来定义参数,但是要注意,自定义的参数一定要有setXXX和getXXX方法,并且在这两个方法中,实现对动画所操作对象的属性设置。

AnimatorSet

AnimatorSet是一系列动画的集合,也可以叫组合动画。

例如:

AnimatorSet animSet = new AnimatorSet();  
            animSet.playTogether(
            ObjectAnimator.ofFloat(mButton, "translationX", -500f, 0f),
            ObjectAnimator.ofFloat(mButton, "rotation", 0f, 360f),
            ObjectAnimator.ofFloat(mButton, "alpha", 1f, 0f, 1f));

AnimatorSet 提供了一个play方法,返回的是一个AnimatorSet.Builder对象,可以进行以下操作:

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

ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);  
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);  
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
AnimatorSet animSet = new AnimatorSet();  
animSet.play(rotate).with(fadeInOut).after(moveIn);  
animSet.setDuration(5000);  
animSet.start();  

以上代码表示旋转和淡入淡出动画同时进行,并把它们插入到了平移动画的后面。

XML动画

XML动画是将属性动画的各项属性在XML中进行设置,功能与代码中设置是一样的,它最大的好处是可以重复引用。
使用XML动画时,首先在res下新建一个animator文件夹,所有的属性动画XML都放在该文件夹下。设置属性动画有以下几个标签:

<animator>: ValueAnimator
<objectAnimator>: ObjectAnimator
<set>: AnimatorSet

示例如下:

<set xmlns:android="http://schemas.android.com/apk/res/android"  
    android:ordering="sequentially" >   
    <Animator  
        android:duration="2000"   
        android:valueFrom="-500"  
        android:valueTo="0"  
        android:valueType="floatType" >  
    </Animator>  
  
    <set android:ordering="together" >  
        <objectAnimator  
            android:duration="3000"  
            android:propertyName="rotation"  
            android:valueFrom="0"  
            android:valueTo="360"  
            android:valueType="floatType" 
            android:startOffset="5"
            android:repeatCount="2"
            android:repeatMode="restart">  
        </objectAnimator>  
        <set android:ordering="sequentially" >  
            <objectAnimator  
                android:duration="1500"  
                android:propertyName="alpha"  
                android:valueFrom="1"  
                android:valueTo="0"  
                android:valueType="floatType" >  
            </objectAnimator>  
            <objectAnimator  
                android:duration="1500"  
                android:propertyName="alpha"  
                android:valueFrom="0"  
                android:valueTo="1"  
                android:valueType="floatType" >  
            </objectAnimator>  
        </set>  
    </set>      
</set>

属性简介:
android:ordering 动画的执行顺序,默认为together,表示各个动画同时执行。sequentially表示顺序执行。
android:propertyName 动画的动作类型,alpha,color,translateX等
android:valueType 属性类型,有intType和floatType两个选项
android:valueFrom/To 初始值和结束值
android:startOffset 动画开始之后,延迟多少时间开始执行
XML使用方法如下:

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);  
//AnimatorSet set = (AnimatorSet ) AnimatorInflater.loadAnimator(context, R.animator.anim_xml);  
animator.setTarget(view);  
animator.start();

Animator监听

Animator类中为我们提供了一个addListener(),它接收一个AnimatorListener作为参数,可以实现对动画开始,结束,重复和取消的监听:

anim.addListener(new AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                // TODO Auto-generated method stub
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
                // TODO Auto-generated method stub
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                // TODO Auto-generated method stub
            }
            @Override
            public void onAnimationCancel(Animator animation) {
                // TODO Auto-generated method stub
            }
        });

如果只需要对某个事件监听,可以用AnimatorListenerAdapter(),它已经内部实现了Listener中的方法,我们可以根据需要覆写自己需要的方法即可

anim.addListener(new AnimatorListenerAdapter() {  
    @Override  
    public void onAnimationEnd(Animator animation) {  
    }  
});  

Interpolator和Evaluator

这两个东西翻译过来可以叫做差值器和估值器。从补间动画开始就支持Interpolator接口了,在属性动画中新增了一个TimeInterpolator接口,它有几种常用实现:

LinearInterpolator:线性差值器,适用于匀速动画
AccelerateInterpolator:加速差值器,运行速度越来越快
DecelerateInterpolator,减速差值器,运行速度越来越慢
AccelerateDecelerateInterpolator:加减速差值器,动画运行时中间速度快,两头速度慢
BounceInterpolator:弹性差值器,模拟弹跳动作。

属性动画默认使用的就是AccelerateDecelerateInterpolator,需要改变差值器设置的时候,调用Animator对象的setInterpolator方法就可以了,参数2f就是我们设置的加速度。:

anim.setInterpolator(new AccelerateInterpolator(2f)); 
anim.setInterpolator(new BounceInterpolator());

那么,Interpolator的作用原理是怎样的呢?看一下TimeInterpolator接口的代码:

public interface TimeInterpolator {   
    float getInterpolation(float input);  
} 

很简单,只是根据input的值来返回一个float数。这里,input是一个从0到1的变化值,在动画的运行过程中,input会从随时间流逝从0匀速变化为1。Interpolator 要做的,就是根据input,通过计算之后,返回我们需要的数值。比如LinearInterpolator,线性差值器,它也是匀速的,所以它什么都没有做,直接在getInterpolation方法中返回了input。

理解了Interpolation之后,还需要介绍一个Evaluator的概念,在上文的例子中我们用到了一个自定义的TypeEvaluator,MyEvaluator,它的作用根据fraction计算当前坐标,封装到Cordinate对象里返回,然后View根据这个坐标来绘制圆形。看到这里,TypeEvaluator的作用就很清楚了,估值器决定了动画在某一个时刻的具体状态。
fraction,这个参数就是我们通过Interpolator中的getInterpolation得到的。也就是说,Interpolator决定了动画的整体变化规律,Evaluator根据这个规律,来实现具体某一时刻的状态。

在上文的例子中,我们是根据fraction来计算圆形的坐标位置,如果是颜色,那么就需要根据fraction来计算颜色的变化并返回封装好的颜色值。Interpolator和Evaluator一起决定了动画的最终表现形式。

ViewPropertyAnimator

ViewPropertyAnimator是专门为View开发的一个辅助类,用起来非常简单,直接调用View对象的.animate()方法,得到一个ViewPropertyAnimator对象,就可以进行动画了

textview.animate().x(500).y(500).setDuration(5000) .setInterpolator(new BounceInterpolator());  

表示在5s内将textView移动到500,500,动画效果是弹跳。

相关文章

网友评论

      本文标题:Android属性动画使用指南

      本文链接:https://www.haomeiwen.com/subject/ddzztxtx.html