android 帧动画的替代方案

在android 里有丰富的动画实现过程,其中帧动画的使用也是非常广泛,比如在网络加载数据的时候我们希望界面中间显示一头老牛努力跑动的效果.
此时我们大多都会选择让美工做好一系列老牛跑动的图片,少则5张,多则10张,图片越多,动画将会越平滑细腻,于是我们兴奋的要求美工,给我来20张!
然后 我们急匆匆的做好帧动画的xml文件,拿到20张漂亮的图片,再然后兴冲冲的去运行看效果,我们悲剧的发现,程序并没有跑起来,而是莫名其妙的闪退了.如果能看到日志,你发觉的闪退的原因其实很简单, OOM!
OMG! 我们最不愿遇到的内存问题.是我们的图片太大吗?还是我们动画间隔太短.我们想尽一切办法想要处理掉这个BUG!
可是我要告诉你,抛弃帧动画吧!因为你不确定在你解决了一台测试机的OOM,就一定能保证在另一台测试机上(可能内存更小)不会重现.
那不使用帧动画我们该如何实现想要的效果呢?

今天我们要使用的技能GET为属性动画.顾名思意,属性动画就是通过不间断改变对象的属性来达到变化的动态效果,什么是属性呢,控件的x,y坐标,控件的旋转角度,控件的缩放大小等等.
当然,属性动画最低版本要求为3.0.因此我们需要舍弃那些已经过时的低版本系统.很幸运的是,目前3.0以下的手机目前整个地球只剩下不到5%的用户,而这5%的用户更不会很幸运的使用你的APP.所以舍弃他们,你将获得新生!

有关低版本兼容问题,想要在这里bi bi 一下,每当一个新的API出现的时候,我们很兴奋它带给我们的新特性,比如透明状态栏,沉浸式等等,但我们不能使用!为的就是这该死的低版本兼容,因为新API出现的时候,整个星球还充斥着低版本的手机,你必须要照顾他们的情绪.什么时候等到这些低版本手机即将被淘汰的时候,我们才敢稍微放肆一点,去沾染这些新的API.太奇怪的这个状态.

好了,言归正传.如何用属性动画实现帧动画的效果呢?这里我们讲一下图片控件(ImageView)的一个特性Level. 我们可以使用level资源为图片设置不同level下的图片.典型的使用就是电量level. 当电量低于0时显示一张空电量的图片,小于10%的时候显示1/10的电量图片….

暂时没有明白level为什么没有出现在imageview的属性列表中,我们只能通过setImageLevel来设置图片的level却无法getImageLevel来获取图片的level.

没关系,我们先来实现我们的level资源吧.

"@drawable/animation1" android:maxLevel="1"/>"@drawable/animation2" android:maxLevel="2"/>"@drawable/animation3" android:maxLevel="3"/>"@drawable/animation4" android:maxLevel="4"/>"@drawable/animation5" android:maxLevel="5"/>"@drawable/animation6" android:maxLevel="6"/>"@drawable/animation7" android:maxLevel="7"/>"@drawable/animation8" android:maxLevel="8"/>"@drawable/animation9" android:maxLevel="9"/>"@drawable/animation10" android:maxLevel="10"/>"@drawable/animation_stop" android:maxLevel="10"/>

很高兴,我们再也不害怕过多的图片导致OOM问题,因为level资源并不会将所有的level图片一次性全部加载.
这里我们甚至可以实现电影般流畅的动画效果而不用但心OOM.

我们将这个资源像普通背景一样设置为图片的src.
但是我们如何让他动起来呢?
查看属性动画的特性我们有如下结论:
- 支持对所有View能更新的属性的动画(需要属性的setXxx()和getXxx())。
但是我们的ImageView并没有level这样一个属性,怎么办呢,我们可以继承ImageView,为它增加这样一个属性:

    // 提供一个用于属性动画操作的图片类。imageLevel不属于ImageView的属性,因此只能自己定义此属性。
    // 并通过属性动画进行修改。
    public static class LevelImageView extends ImageView {
        public LevelImageView(Context context) {
            super(context);
        }
        private int imageLevel = 0;
        public void setImageLevel(int level) {
            if (this.imageLevel == level)
                return;
            super.setImageLevel(level);
            this.imageLevel = level;
        }
        public int getImageLevel() {
            return imageLevel;
        }
        // 下一level接口。
        public void nextLevel() {
            setImageLevel(imageLevel++ % maxLevel);
        }
        private int maxLevel = 10;

        public void setMaxLevel(int maxLevel) {
            this.maxLevel = maxLevel;
        }
    }

如此我们就可以像普通的属性一样来操纵level属性了.

我们粗暴一点上代码吧.

LevelImageView imageView = new LevelImageView(getContext());
//设置level资源.
imageView.setImageResource(R.drawable.drawable_refresh_image);        imageView.setScaleType(ScaleType.CENTER_INSIDE);
//新建动画.属性值从1-10的变化
headerAnimator = ObjectAnimator.ofInt(imageView, "imageLevel", 1, 10);
//设置动画的播放数量为一直播放.
 headerAnimator.setRepeatCount(ObjectAnimator.INFINITE);
 //设置一个速度加速器.让动画看起来可以更贴近现实效果.
 headerAnimator.setInterpolator(new LinearInterpolator());
 headerAnimator.setRepeatMode(ObjectAnimator.RESTART);
 headerAnimator.setDuration(600);
 headerAnimator.start();

这样动画就开始了,他通过不停的改变imageLevel属性达到显示不同图片的效果,
当然你也可以很随意的控制这个动画暂停,重播,停止等等.不像帧动画 无法灵活控制.

以后就可以全面使用属性动画来替代补间动画和帧动画了.

你可能感兴趣的:(android)