Android的三种动画实现(使用XML编写动画)

原文链接:http://www.jianshu.com/p/51d087c11086

1.逐帧动画
逐帧动画的工作原理:就是将完整的动画拆分成一张张单独的图片,然后再将它们连贯起来播放,类似于动画片的工作原理。
2.补间动画
补间动画的工作原理:就是对view进行一系列的动画操作,包括淡入淡出,平移,缩放,旋转四种。
3.属性动画
Android3.0版本。系统提供给了我们一种全新的动画模式。属性动画(property animation),弥补了补间动画的一些缺陷,几乎是可以完全替代掉补间动画。
(1)为什么要引入属性动画?
补间动画还是比较健全的,比如说对view进行移动,旋转,缩放,淡入淡出等等。并且我们还可以借助AnimationSet来将这些动画效果组合起来使用,除此之外还可以通过配置Interpolator来控制动画的播放速度等等。一旦我们的需求超出了移动、缩放、旋转和淡入淡出这四种对View的操作,那么补间动画就不能再帮我们忙了,也就是说它在功能和可扩展方面都有相当大的局限性,那么下面我们就来看看补间动画所不能胜任的场景。
1.1、如果我们对非view的对象进行动画操作,就不可以使用补间动画。
1.2、如果我们希望对view的背景色进行改变,补间动画也是实现不了的。它只是改变了view的显示效果而已,而不是真正去改变view的属性。
新引进的属性动画已经不再是针对view进行设计的了。也不限定只能实现移动,旋转,缩放,淡入淡出这几种动画效果,同时也不再只是视觉上的一种动画效果。它实际上是一种不断对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性。所以我们仍然可以将一个View进行移动或者缩放,但同时也可以对自定义View中的Point对象进行动画操作了。我们只需要告诉系统动画的(运行时长),需要执行(哪种类型的动画),以及动画的(初始值)和(结束值),剩下的工作就可以全部交给系统去完成了。
1.ValueAnimator类
属性动画的机制是通过不断的对值的操作来实现的,而初始值和结束值之间的动画过度就是通过ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过度。我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画运行所需要的时长。那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等。

//设置动画的初始值和结束值以及运行时长。
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(300);
anim.start();

ofFloat()方法当中允许传入多个float类型的参数
setDuration()方法来设置动画运行的时长
start()方法启动动画

anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float currentValue = (float) animation.getAnimatedValue();
        Log.d("TAG", "animation value is " + currentValue);
    }
});

通过addUpdateListener()方法来添加一个动画的监听器
2.ObjectAnimator类
它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。
它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似,这里如果我们想要将一个TextView在5秒中内从常规变换成全透明,再从全透明变换成常规,就可以这样写:

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

ofFloat()方法来去创建一个ObjectAnimator的实例。
ofFloat()方法当中接收的参数:第一个参数要求传入一个object对象,我们想要对哪个对象进行动画操作就传入什么。第二个参数是想要对该对象的哪个属性进行动画操作。后面的参数就是不固定长度了,想要完成什么样的动画就传入什么值
setDuration()方法来设置动画的时长
start()方法启动动画
旋转

ObjectAnimator animator = ObjectAnimator.ofFloat(tv_name, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();

平移

float curTranslationX = tv_name.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(tv_name, "translationX", curTranslationX, -600f, curTranslationX);
animator.setDuration(5000);
animator.start();

缩放

ObjectAnimator animator = ObjectAnimator.ofFloat(tv_name, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();

其实ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法,因此alpha属性所对应的get和set方法
实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作

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

Animator监听器
我们希望监听到动画的各种事件,比如动画何时开始,何时结束。然后在开始或者结束去执行一些逻辑处理。这个功能是完全可以实现的。Animator类当中提供了一个addListener()方法。这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件。
ObjectAnimator、ValueAnimator,AnimatorSet都是继承自Animator类的。因此addListener()这个方法算是一个通用的方法。

animator.addListener(new Animator.AnimatorListener() {

@Override
public void onAnimationStart(Animator animation) {

}

@Override
public void onAnimationEnd(Animator animation) {

}

@Override
public void onAnimationCancel(Animator animation) {

}

@Override
public void onAnimationRepeat(Animator animation) {

}
});

onAnimationStart()方法会在动画开始的时候调用
onAnimationRepeat()方法会在动画重复执行的时候调用
onAnimationEnd()方法会在动画结束的时候调用
onAnimationCancel()方法会在动画被取消的时候调用
2.使用XML编写动画
通过xml来编写动画可能会比通过代码来编写动画要慢一些。但是在重用方面会变得非常轻松,比如某个将通用的动画编写到xml中。我们可以在各个界面轻松的重用它。
如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:
<animator> 对应代码中的ValueAnimator
<objectAnimator> 对应代码中的ObjectAnimator
<set> 对应代码中的AnimatorSet

<?xml version="1.0" encoding="utf-8"?>
<animator  xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0"
    android:valueTo="100"
    android:valueType="intType"/>
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator  xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="1"
    android:valueTo="0"
    android:valueType="floatType"
    android:propertyName="alpha"/>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">

    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-500"
        android:valueTo="0"
        android:valueType="floatType"/>

    <set android:ordering="together">
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType"/>

        <set android:ordering="sequentially">
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType"/>
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </set>
</set>

使用xml设置动画
Animator animator = AnimatorInflater.loadAnimator(getApplicationContext(), R.animator.animator3);
animator.setTarget(tv_name);
animator.start();

展开阅读全文

没有更多推荐了,返回首页