Android onDraw触发ImageView的setImageBitmap实现动画,可见时执行动画,不可见时自动停止动画

版权声明:本文为Zhang Phil原创文章,请不要转载! https://blog.csdn.net/zhangphil/article/details/81980357

Android onDraw触发ImageView的setImageBitmap实现动画,可见时执行动画,不可见时自动停止动画

一个简单的小例子,这个例子首先从assets读取出若干张图片作为Bitmap资源,然后在onDraw里面每个25ms触发一次ImageView的setImageBitmap,这样做以25ms作为周期,循环的每隔25ms重新设置ImageView的图片源,达到动画效果,这样做的好处是,由于onDraw只在可见状态下重绘才调用,如果当前的自定义的ImageView不可见,自动就停止执行动画,比较节能。

package zhangphil.test;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.Log;

import java.io.InputStream;

public class LoadingImageView extends AppCompatImageView {
    private String TAG = "加载动画";
    private Context mContext;
    private Bitmap[] mBitmaps;

    private int i = 0;
    private int WHAT = 0xfc01;

    /**
     * 是否执行动画,如果为false,不需要动画逻辑。
     * 默认true执行。
     */
    private boolean mAnimationEnable = true;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == WHAT) {
                mHandler.removeMessages(WHAT);

                //Log.d(TAG, "设置新动画图片");
                setImageBitmap(mBitmaps[i++ % mBitmaps.length]);
            }
        }
    };

    public LoadingImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        mContext = context;
        init();
    }

    /**
     * true,当该View可见状态下就执行动画。
     * false,当前View无论处于何种状态都不执行动画。
     *
     * @param enable
     */
    public void setAnimationEnable(boolean enable) {
        mAnimationEnable = enable;
    }

    private void init() {
        mBitmaps = getBimaps();
        if (!isResOk()) {
            Log.e(TAG, "动画资源为空!");
            return;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //Log.d(TAG, "onDraw");

        if (mAnimationEnable && isResOk()) {
            mHandler.sendEmptyMessageDelayed(WHAT, 25);
        }
    }

    private boolean isResOk() {
        return mBitmaps != null && mBitmaps.length > 0;
    }

    /**
     * 从assets目录下读取图片资源放到数组里面,作为连续动画的资源图。
     *
     * @return
     */
    private Bitmap[] getBimaps() {
        final String parentPath = "loading";

        Bitmap[] bitmaps = null;
        AssetManager am = mContext.getAssets();
        try {
            String[] files = am.list(parentPath);
            bitmaps = new Bitmap[files.length];
            for (int i = 0; i < files.length; i++) {
                InputStream is = am.open(parentPath + "/" + files[i]);
                bitmaps[i] = BitmapFactory.decodeStream(is);
                is.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmaps;
    }
}

使用方法和普通的ImageView一样,这个自定义LoadingImageView比较适合下拉刷新时候头部的滚动圆球动画制作和实现。

出于兼容高版本的目的,在上层Java代码主动调用一次动画的start方法触发动画:

        ImageView mImageView = findViewById(R.id.load_image);
        AnimationDrawable mAnimationDrawable = (AnimationDrawable) mImageView.getDrawable();
        mAnimationDrawable.start();

因为代码需要从assets目录下的loading目录下读取图片作为动画素材,因此需要事先在项目的assets目录下放置一系列要连续加载的图片。

猜你喜欢

转载自blog.csdn.net/zhangphil/article/details/81980357
今日推荐