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);
}
相關文章
相關標籤/搜索