版权声明:本文为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目录下放置一系列要连续加载的图片。