YY项目之帧动画(二)

YY项目之帧动画(一)中咱们介绍了帧动画的基本使用。
java

可是若是美工给咱们的图片都是几百 * 几百的,加载进不一样的分辨率的手机中,占用的内存是显而易见的。android

并且,在个人项目中,会常常出现OOM,因此下面就来解决由帧动画引发的OOM问题。ide

由前面的文章能够知道,这个需求主要实现framelayout的上面一层来实现动画,底下的层用来实现须要展现的视图。
优化

因此,底下的视图层照常编辑便可。动画

若是须要解决帧动画加载内存占用的问题,就不能加载编辑好的drawable文件夹中的xml文件了,须要手动编辑java代码,在java代码层面处理生成AnimationDrawable(这里是关键的思想)。spa

使用java代码建立AnimationDrawable的好处是:动态的按需处理加载进内存的图片的像素,从而优化了内存占用过多(甚至发生OOM)的问题。.net

那么,接下来,就看看代码是如何实现的吧,只列举其中的一个AnimationDrawable动画。rest

  • 手动建立AnimationDrawable,并设置到指定的View上code

/**
 * 初始化 点击的动画
 */
clickDrawable = new AnimationDrawable();
clickDrawable.setOneShot(true);
for (int i = 0 ;i < 9 ;i++) {
    if (i == 0 || i == 8) {
        // 添加透明的帧
        clickDrawable.addFrame(getResources().getDrawable(R.drawable.transpanrent), 50);
    } else {
        int resId = getResources().getIdentifier("click_" + (i - 1), "mipmap", getPackageName());
        clickDrawable.addFrame(new BitmapDrawable(getResources(), ImageLoaderUtils.decodeSampledBitmapFromResource(getResources(), resId, 100, 100)), 50);
    }
}
iv_anim.setImageDrawable(clickDrawable);

    里面须要用到的透明的效果的xml文件:xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="@android:color/transparent"/>
    <stroke android:color="@android:color/transparent"/>
</shape>
  •  设置点击事件,执行动画:

iv_click.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        if (right) {
            if (!isLongClick) {
                restartAnimation(clickDrawable);
            }
        } else {
            // 显示红色背景
            showWrong();
        }
    }
});

    关键代码片断:

/**
 * 从新启动动画
 * 首先得中止帧动画,而后才能从新执行帧动画,不然没有效果
 *
 * @param drawable
 */
private void restartAnimation(AnimationDrawable drawable) {
    if (drawable.isRunning() && drawable != null) {
        drawable.stop();
    }
    drawable.start();
}

    ImageLoaderUtils 解决该问题的关键方法源码:

/**
 * 计算图片的缩放比例 <br/>
 * 做者 :dengjie zhang <br/>
 * created at 2016/3/16 9:25
 */
public static int calculateInSampleSize(BitmapFactory.Options options,
                                        int reqWidth, int reqHeight) {
    // 源图片的高度和宽度
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        // 计算出实际宽高和目标宽高的比率
        final int heightRatio = Math.round((float)height / (float)reqHeight);
        final int widthRatio = Math.round((float)width / (float)reqWidth);
        // 选择宽和高中最小的比率做为inSampleSize的值,这样能够保证最终图片的宽和高
        // 必定都会大于等于目标的宽和高。
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

/**
 * 获取合适的大小的图片的bitmap的形式 <br/>
 * 做者 :dengjie zhang <br/>
 * created at 2016/3/16 9:27
 */
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                     int reqWidth, int reqHeight) {
    // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    // 调用上面定义的方法计算inSampleSize值
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    // 使用获取到的inSampleSize值再次解析图片
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
相关文章
相关标签/搜索