从一个新的角度开始学习Android属性动画

关于属性动画的博客。网上已经有很多了。我看的第一篇属性动画的博客就是鸿洋的博客:http://blog.csdn.net/lmj623565791/article/details/38067475
学习并应用之后,觉得收获颇丰,并写下一篇博客。

装逼如风,常伴我身

1、新的角度开始——改变ImageResource的例子

有一个这样的需求:用显示一个图片,两秒钟之后换成另一张图片。这种需求很简单,代码也非常简单:

    new Handler().postDelayed(new Runnable() {
          @Override
          public void run() {
               ivImg.setImageResource(R.drawable.f021);
          }
    }, 2000);

调用Handler的postDelayed,非常简单就实现了。
用属性动画的写法,运行发现效果是一样的:

    ObjectAnimator objectAnimator = ObjectAnimator.ofInt(ivImg, "ImageResource", R.drawable.love, R.drawable.f021);
    objectAnimator.setDuration(2000);
    objectAnimator.start();

效果如下:


图片改变的效果

如果从来没有用过属性动画,可能心里的想法是这样的。

还有这种操作?

属性动画(Property Animation)顾名思义就是通过动画的方式改变对象的属性了。既然是属性动画,那就不仅仅限于平移、缩放等动画了。ImageResources也是ImageView的一个属性,当然可以用属性动画来改变的。
可以再来个例子,改变BackgroundColor属性:

    ObjectAnimator objectAnimator = ObjectAnimator.ofInt(ivImg, "BackgroundColor",getResources().getColor(R.color.colorAccent), 
getResources().getColor(R.color.colorPrimary));
    objectAnimator.setDuration(1000);
    objectAnimator.start();

效果如下:

从红色变为蓝色

为什么会有很多颜色的变化呢?
这个属性动画控制的属性值是:R.color.colorAccent到R.color.colorPrimary的变化。这个属性动画控制的属性是:BackgroundColor。通俗一点就是说,在1秒钟之内这个ImageView调用了很多次setBackgroundColor方法,传入的参数是R.color.colorAccent到R.color.colorPrimary变化的值。
所以:
就是有这种操作

2、基本用法

2.1 相关API

一些主要的执行类:
ObjectAnimator 动画的执行类,后面介绍。
ValueAnimator 动画的执行类,后面介绍 。
TypeEvaluator 类型估值,后面的估值器会用到。
TimeInterpolator 时间插值,后面的插值器会用到。
AnimatorSet 多个动画,后面的多个动画会用到。
PropertyValuesHolder 属性值持有类,后面的多个动画会用到。

一些常用的方法:
setDuration()设置动画的持续时间,默认300ms。
start() 开始动画。
setRepeatCount()动画执行的次数
多个动画会用到一些表示动画执行次序的方法。
with() playTogether() 等。

一些常用的监听回调:
AnimatorUpdateListener ValueAnimator用来获取值的变化。
AnimatorListenerAdapter、AnimatorListener 动画状态的监听。

2.2 ObjectAnimator

ObjectAnimator是ValueAnimator的子类。在这里先介绍ObjectAnimator是因为ObjectAnimator实现起来比较简单,也比较容易明白。ValueAnimator会在后面介绍。

初始化一个动画

初始化一个ObjectAnimator的代码是:ObjectAnimator.ofxxx() 方法。xxx跟据需要改变属性值的类型来确定。改变的属性值为int类型,那么初始化时就是.ofInt();改变的属性值为float类型,那么初始化时就是.ofFloat();

例如上面写过的改变BackgroundColor的例子:
这个例子用的就是ofInt。如果换成ofFloat:

setBackgroundColor

因为setBackgroundColor需要传入的参数为int类型,所以会报标红线。以上代码是能够编译通过的,只是执行没有任何效果。


错误的属性值

常用初始化ObjectAnimator的ofFloat()方法:

    public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
        anim.setFloatValues(values);
        return anim;
    }

第一个参数target:传入需要动画的view。
第二个参数propertyName:属性的名称。比如平移translationX或者translationY;上面提到的背景BackgroundColor。传这个参数是有规定的。找到view的setXXX属性的方法,截取方法名set后面的一段就是propertyName。例如:设置View的水平平移属性方法是setTranslationX,那么这个propertyName就是translationX。

第三个参数float... values:这是一个不定参数,这里代表属性值的变化阶段。比如我传两个参数:0f,1f。那么变化值就是0f到1f。 如果我传三个参数:0f,1f,2f那么变化值就是0f 到 1f 到 2f,以此类推。

实现一个基本动画的代码:

    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivImg, "translationX", 0f, 400f);
    objectAnimator.setDuration(2000);
    objectAnimator.start();

2.3 ValueAnimator

初始化ValueAnimator也有很多.ofxxx的方法。但是这些方法明显要比ObjectAnimator少很多。


ValueAnimator的初始方法

同样看下ofFloat的方法,这里只需要传入一个不定参数values就行了:

   public static ValueAnimator ofFloat(float... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setFloatValues(values);
        return anim;
    }

初始化一个ValueAnimator:

   ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,400f);
   valueAnimator.setDuration(1000);
   valueAnimator.setTarget(view); 
   valueAnimator.start();

和ObjectAnimator对比之后会发现,ValueAnimator没有设置需要操作的属性,也不提供类似setPopertyName()的方法。虽然提供了setTarget()的方法指定那个view进行动画,但是由于没有设置需要操作的属性,执行以上代码是不会有任何效果的。但是以上代码控制了值的变化,这里会控制值从0f到400f,只要拿到值变化的就可以控制view的属性值的变化了。用AnimatorUpdateListener来获取变化的值:

    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 400f);
    valueAnimator.setDuration(1000);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                Log.i(TAG, value + "");
                view.setTranslationX(value);
          }
     });
     valueAnimator.start();
07-06 22:21:53.744 22054-22054/com.mg.axe.animation I/BasisAnimationView: 0.0
... ...  此次省略数条Log
07-06 22:21:54.747 22054-22054/com.mg.axe.animation I/BasisAnimationView: 400.0

animation.getAnimatedValue()这个方法可以获取到变化的值。
从log中也可以看到,在一秒钟之内,获取到的值从0f到400f。获取到变化的值之后调用view.setXXX来不停的改变view的属性。以上代码实现了平移到400f的效果。

2.4 多个动画

三种方法可以实现多个动画集合:

1、使用AnimatorSet
    ObjectAnimator translationX = ObjectAnimator.ofFloat(ivImg, "translationX", 0f, 400f);
    ObjectAnimator translationY = ObjectAnimator.ofFloat(ivImg, "translationY", 0f, 400f);
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.play(translationX).with(translationY);
    animatorSet.setDuration(1000);
    animatorSet.start();
2、使用ObjectAnimator.ofPropertyValuesHolder
    PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", 0f, 400f);
    PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", 0f, 400f);
    ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ivImg, translationX,translationY);
    animator.setDuration(1000);
    animator.start();
3、使用ValueAnimator
   ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 400f);
   valueAnimator.setDuration(1000);
   valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float value = (float) animation.getAnimatedValue();
            ivImg.setTranslationX(value);
            ivImg.setTranslationY(value);
        }
   });
   valueAnimator.start();

这三种方法都是控制view向水平和垂直方向移动。相比较来说,使用ValueAnimator会更加灵活。

2.5 AnimatorListener 监听动画状态

属性动画的状态可以通过AnimatorListener接口来回调。

动画状态接口回调

AnimatorListener有四个需要实现的方法,代表动画不同状态的回调。
但是会遇到一种情况,我只需要知道动画的一个状态回调就行了,其他的三个状态没有必要。很显然AnimatorListener无法满足这个要求,这里需要AnimatorListenerAdapter。

AnimatorListenerAdapter

从源码可以看出,AnimatorListenerAdapter是一个抽象类,实现了AnimatorListener。当使用AnimatorListenerAdapter时,只要重写需要用到的方法就行了。

AnimatorListenerAdapter的使用

2.6 估值器 Evaluator

估值器就是动态干预属性变化的值:

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 400f);
        valueAnimator.setDuration(1000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                Log.i(TAG, value + "");
                view.setTranslationX(value);
            }
        });
    valueAnimator.start();

以上属性动画值从0f到400f。 animation.getAnimatedValue()的值也是0f到400f之间的变化值。如果现在需要 animation.getAnimatedValue() 返回的值发生改变,这里就需要用到估值器了:

    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 400f);
    valueAnimator.setDuration(1000);
    valueAnimator.setEvaluator(new TypeEvaluator<Float>() {
        @Override
        public Float evaluate(float fraction, Float startValue, Float endValue) {
            Log.i(TAG, "startValue:" + startValue);
            Log.i(TAG, "endValue:" + endValue);
            Log.i(TAG, "fraction:" + fraction);//o -1
            return fraction * endValue;
        }
    });
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                ivImg.setTranslationX(value);
            }
    });
   valueAnimator.start();

evaluate方法中的三个参数:
fraction: float值从0f-1f变化。这里会在1秒钟之内从0f到1f。
startValue和endValue就是ofFloat()传入的开始值:0f和结束值400f。
在evaluate方法中返回不同的值,在AnimatorUpdateListener中的 animation.getAnimatedValue()就会获取到不同的值。
总之,估值器是一个非常实用的工具,它可以动态干预属性值的变化。可以自定义估值器来应对不同的需求。

2.7 插值器 Interpolator

属性值从初始值过渡到结束值的变化率,比如说加速,减速等等。系统已经提供了一些插值器,也可以自定义插值器。
弹跳效果的插值器的效果:

        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivImg, "translationX", 0f, 400f);
        objectAnimator.setDuration(1000);
        objectAnimator.setInterpolator(new BounceInterpolator());
        objectAnimator.start();
弹跳插值器

setInterpolator的方法:

@Override
    public void setInterpolator(TimeInterpolator value) {
        if (value != null) {
            mInterpolator = value;
        } else {
            mInterpolator = new LinearInterpolator();
        }
    }

TimeInterpolator是个接口,系统实现了很多插值器。


插值器

3、总结

这文主要介绍一些动画的基本用法,也是自己学习属性动画的一个笔记。关于自定义插值器和估值器,有时间在去研究再写博客。
贴上大牛博客的地址:
http://blog.csdn.net/lmj623565791/article/details/38067475
http://www.jianshu.com/p/2412d00a0ce4
最后:

结束

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容