Android动画学习总结---下

终于来到本系列动画总结的最终篇,前面两篇博客 Android动画学习总结---上 Android动画学习总结---中 分别总结了View Animation和Frame Animation的基本用法。接下将会总结Property Animation属性动画的基本用法。

一、Property Animation属性动画

关键类和接口总结:
ValueAnimator:这个ObjectAnimator的基类,主要用来在动画变化过程中通过ofInt,ofFloat等静态方法手动修改目标对象的属性。使用方法比较灵活,具体用法请看下面的代码样例。
ObjectAnimator:其是ValueAnimatior的子类,也可以使用上面ofInt,ofFloat等方法。不需要手动更新目标对象属性,操作简便。
TypeEvaluator:一个接口,通过该接口可以实现自定义的Evaluator(求值器)详细用法请看样例。
AnimatorSet:动画集合类(这里需要注意的是这个AnimatorSet与补间动画的AnimationSet不同)

这里需要注意 AnimationSet 与 AnimatorSet 最大的不同在于,AnimationSet 使用的是 Animation 子类、AnimatorSet 使用的是 Animator 的子类。
Animation 是针对视图外观的动画实现,动画被应用时外观改变但视图的触发点不会发生变化,还是在原来定义的位置。
Animator  是针对视图属性的动画实现,动画被应用时对象属性产生变化,最终导致视图外观变化。

动画监听器总结
Animator.AnimatorListener接口
需要实现的方法
onAnimationStart()动画启动回调
onAnimationEnd()动画结束回调
onAnimationRepeat()动画重复播放回调
onAnimationCancel()动画被取消时回调
代码样例如下
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 350);
valueAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animator) {
        Log.e("-------------->", "动画开始");
    }

    @Override
    public void onAnimationEnd(Animator animator) {
        Log.e("-------------->", "动画结束");
    }

    @Override
    public void onAnimationCancel(Animator animator) {
        Log.e("-------------->", "动画取消");
    }

    @Override
    public void onAnimationRepeat(Animator animator) {
        Log.e("-------------->", "动画重复");
    }
});
如果觉得上面有太多的实现方法,写起来太恶心。也可以使用AnimatorListenerAdapter抽象类,这个抽象类实现Animator.AnimatorListener和Animator.AnimatorPauseListener接口,因此在使用的时候可以选择性的覆盖方法。
使用样例如下所示
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 350);
valueAnimator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);
    }
    
});
在这里我选择覆盖了onAnimationStart方法。
可以看到这个抽象类可以选择覆盖的方法有5个(如下图所示)


ValueAnimator.AnimatorUpdateListener接口
需要实现的方法
onAnimationUpdate()动画每帧都会调用该方法。咋们可以通过getAnimatedValue得到当前帧的值。
这个监听接口很重要,我将会在下面的样例提及。

二、ObjectAnimator编码方式的样例
在这个样例中的属性值我使用了scaleX意味着动画只沿着X轴缩放。属性对象是一个ImageView,缩放的范围是1.0f到3.0f
//第一个参数表示操作对象,第二个参数表示属性值,第三个参数表示属性值的起始值,第四个参数表示属性值的结束值
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1.0f, 3.0f);
//动画持续时间
objectAnimator.setDuration(3000);
//动画开始
objectAnimator.start();


值得注意的是,这个ObjectAnimator是直接修改目标对象的属性值来达到动画变化的目的,例如下面的属性值scaleX,那么你的目标对象ImageView必要有setScaleX的方法(事实上ImageView确实有这个方法)。
如图所示


假如你随便写个属性值helloworld,你会发现ImageView没有任何变化,因为没有setHelloworld的方法啊。
所以咋们基本明白,ObjectAnimator.ofFloat()方法的第二个参数除了写scaleX之外,还可以写
translationX,translationY,rotaionX,rotationY等(这些属性大部分视图都会实现的)
Property Animation属性动画的属性值
translationX和translationY:平移
rotation,rotationX和rotationY:旋转
scaleX,scaleY:缩放
alpha:透明度

三、ValueAnimator编码方式的样例
这个ValueAnimator的用法如果你仔细看,你会发现和ObjectAnimator的用法有很大的用法。

首先,在ValueAnimator.ofInt(0,350)发现,已经没有再要求写入目标对象了并且属性值也没有了,只保留了起始值和结束值。(当如果再极端一点,可以连起始值都不写,只写结束值350,系统会默认从0开始变化到350)

其次,ValueAnimator需要手动通过ValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener())实现目标对象的更新和处理。

这里主要说明:动画变化过程中每帧都会回调该方法。通过valueAnimator.getAnimatedValue()可以获取0-350之间的整数值
//注意这里是使用了ofInt这个静态方法。表示从初始值0到结束值350之间变化
//这里面变化的数值都是整型。(如果使用ofFloat(0,350)则之间变化的值就是float类型)
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 350);
valueAnimator.setTarget(imageView);
//这个Interpolator用来改变动画的播放速率,BounceInterpolator是系统已经帮我们定义好的速率。
//如果对变化速率没有要求,则下面一行代码可以不写。
valueAnimator.setInterpolator(new BounceInterpolator());
valueAnimator.setDuration(5000);
valueAnimator.start();

//由于上面ValueAnimator没有直接操作对象的属性。所以只能在监听器里面手动操作(这一点与ObjectAnimator不同)。
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        //通过valueAnimator.getAnimatedValue()获取某一帧的动画值。
        imageView.setTranslationY((int) valueAnimator.getAnimatedValue());

        Log.e("-------------->", "变化值都是整型" + (int) valueAnimator.getAnimatedValue());
    }
});
效果如图所示


可能你会问,这仅仅是改变了ImageView的平移属性,如果我想同时改变其它属性怎么办?
这里,我们对上面的代码做一些改动,先将ValueAnimator.ofInt()改为ValueAnimator.ofFloat()目的是让动画的变化过程更加流畅自然。
其次在onAnimationUpdate添加动画变化的属性。
修改后的代码如下所示
//修改了ofInt为ofFloat
valueAnimator = ValueAnimator.ofFloat(350);
valueAnimator.setTarget(imageView);
//这个Interpolator用来改变动画的播放速率,BounceInterpolator是系统已经帮我们定义好的速率。
//如果对变化速率没有要求,则下面一行代码可以不写。
valueAnimator.setInterpolator(new BounceInterpolator());
valueAnimator.setDuration(5000);
valueAnimator.start();

//由于上面ValueAnimator没有直接操作对象的属性。所以只能在监听器里面手动操作(这一点与ObjectAnimator不同)。
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        //通过valueAnimator.getAnimatedValue()获取某一帧的动画值。
        imageView.setTranslationY((float) valueAnimator.getAnimatedValue());
        //添加如下三个属性,ScaleX和ScaleY除以50的目的是控件缩放比例(如果不除以,整个屏幕都是背景图咋看啊!)。
        imageView.setScaleX((float) valueAnimator.getAnimatedValue() / 50);
        imageView.setScaleY((float) valueAnimator.getAnimatedValue() / 50);
        imageView.setRotation((float) valueAnimator.getAnimatedValue());
        Log.e("-------------->", "变化值都是float类型" + (float) valueAnimator.getAnimatedValue());
    }
});
效果如图所示


看了惯了上面的ValueAnimator().ofInt,或者ValueAnimator().ofFloat,也许会问如果我的值不是Int或Float类型怎么办?这时候就是咋们还可以重写TypeEvaluator定义自己的变量类型。

首先,设置一个对象类型setObjectValues(new PointF())
其次, 设置setEvaluator(new TypeEvaluator<PointF>())重写里面evaluate的方法,在这里定义自己的计算公式。注意这个方法将会在指定的Duration时间段内反复调用并且返回一个你先前设置的对象(PointF)。
最后,通过valueAnimator1.addUpdateListener监听器获取evaluate方法每次返回的值。
//直接new了一个对象,这里没有想上面那样去调用ofInt或ofFloat等静态方法。
ValueAnimator valueAnimator1 = new ValueAnimator();
valueAnimator1.setDuration(3000);
//设置一个对象
valueAnimator1.setObjectValues(new PointF());
//自定义类型
valueAnimator1.setEvaluator(new TypeEvaluator<PointF>() {
    @Override
    public PointF evaluate(float v, PointF pointF, PointF t1) {
        PointF pointF1 = new PointF();
        //一个物理公式速度乘以时间
        pointF1.x = 700 * v;
        //也是公式速度乘以时间平方除以2(其中550表示在550PX的地方开始下落)
        pointF1.y = (700 * v * v) / 2+550;
        return pointF1;

    }
});

valueAnimator1.start();
valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        PointF pointF = (PointF) valueAnimator.getAnimatedValue();
        imageView.setX(pointF.x);
        imageView.setY(pointF.y);
        Log.e("-------------------->测试", pointF.x + "     " + pointF.y);
    }
});
效果如图所示


五、AnimatorSet编码方式的样例
简单来说这是一个播放动画的集合。
主要注意,播放动画的方法类型。
playTogether(同时播放),
playSequentially(按顺序播放)。

play(动画对象1).with(动画对象2)。表示同时播放动画1和动画2
先放大后放小
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1.0f, 5.0f);
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "scaleY", 1.0f, 5.0f);

ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView, "scaleX", 5.0f, 1.0f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(imageView, "scaleY", 5.0f, 1.0f);
AnimatorSet animatorSet = new AnimatorSet();
//设置动画的持续时间5秒
animatorSet.setDuration(5000);
//设置动画的播放速率
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
//设置objectAnimator和objectAnimator1一起缩放变大
animatorSet.play(objectAnimator).with(objectAnimator1);
//在objectAnimator1执行完毕之后,设置objectAnimator2和objectAnimator3缩放变小。
animatorSet.play(objectAnimator2).with(objectAnimator3).after(objectAnimator1);

animatorSet.start();
效果图


按顺序播放先平移后缩放
ValueAnimator valueAnimator = ValueAnimator.ofInt(500);
valueAnimator.setTarget(imageView);
valueAnimator.setDuration(3000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        imageView.setTranslationY((int) valueAnimator.getAnimatedValue());
    }
});

ValueAnimator valueAnimator1 = ValueAnimator.ofFloat(1.0f, 5.0f);
valueAnimator1.setTarget(imageView);
valueAnimator1.setDuration(5000);
valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        imageView.setScaleX((float) valueAnimator.getAnimatedValue());
        imageView.setScaleY((float) valueAnimator.getAnimatedValue());
    }
});
AnimatorSet animatorSet1 = new AnimatorSet();
//同时播放
animatorSet1.playTogether(valueAnimator, valueAnimator1);
animatorSet1.start();
效果图


六、在XML中声明动画(属性动画类对应的xml标签如下)
valueAnimatior       ------      <animator>
objectAnimatior      ------      <objectAnimator>
AnimationSet          ------      <set>

set是根元素在set之中可以包含若干个set,animator,objectAnimator。
set有一项十分中的的属性android:ordering="together|sequentially", togetther表示同时运行动画,sequentially表示按顺序执行动画。

基本都讲得差不多了,首先在res/animator文件夹下(没有animator文件夹请自行创建)创建一个animator.xml文件,代码如下
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">
    <set android:ordering="sequentially">
        <objectAnimator
            android:propertyName="scaleX"
            android:repeatCount="5"
            android:repeatMode="reverse"
            android:valueFrom="1.0"
            android:valueTo="2.0" />

        <objectAnimator
            android:propertyName="scaleY"
            android:repeatCount="5"
            android:repeatMode="reverse"
            android:valueFrom="1.0"
            android:valueTo="2.0" />
    </set>

    <objectAnimator
        android:duration="500"
        android:propertyName="alpha"
        android:repeatCount="5"
        android:valueFrom="0f"
        android:valueTo="1f" />

</set>

接下来就直接在代码中加载此文件即可!
//加载动画XML文件,loadAnimator第一个参数传入context,第二个参数表示动画Xml源文件
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.animator);
animator.setTarget(imageView);
animator.start();
效果如图所示


xml的基本用法大概就这样,我也不再举其它例子啦。

、结束
结束啦,三遍动画系列的博客终于总结完毕。对于Android整个动画框架还有一
部分动画的使用还没讲,由于最近项目工作量比较大,我也不打算再继续写。等以后有空再研究研究。
谢谢各位捧场啊^_^

源代码请戳这里Android动画学习总结---下

参考资料:
http://blog.sina.com.cn/s/blog_b991f82a0101gqa3.html




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值