最近在做帧动画,由于AnimationDrawable其实就是个Drawable,本身并没有监听,研究了很多方法,网上的方法都是通过启动一个Handler,延时停止动画,这种方法虽然能实现,但是有个很大的问题,就是假如机器卡顿,那么动画就和Handler不同步了,动画持续时间越长,这个问题就越严重,于是各种查找方法,最后在API中发现了一行没有注释的代码,对,就是没有注释,结果就让我忽略的方法
getCurrent() 获取当前帧,得到的是一个 Drawable
然后想到能够获取指定帧的 Drawable,那么我们直接拿到最后一帧的 Drawable和当前帧做比较不就行了?就是如此
getFrame(int i) 获取指定帧的 Drawable
getNumberOfFrames() 获取总帧数
最终组合成核心代码
getFrame(getNumberOfFrames() -1) != getCurrent()
最后自定义个接口来实现监听就搞定啦
/**
* 作 者:MrYan (QQ:416643088)
* 创建日期:8/6 0006.
* 带回调的帧动画
*/
public class MyFrameAnimation extends AnimationDrawable {
private Handler handler;
private Runnable runnable;
private OnFrameAnimationListener onFrameAnimationListener;
private int maxDuration;
public MyFrameAnimation() {
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
//获取最后一帧,和当前帧做比较,如果相等,就结束动画,调用动画结束回调
if (getFrame(getNumberOfFrames() - 1) != getCurrent()) {
initHandler(); //如果不是最后一帧,重新启动handler
} else {
unRunning(); //如果是最后一帧,触发结束回调
}
}
};
}
/**
* 动画不在运行,触发结束回调
*/
private void unRunning() {
if (onFrameAnimationListener != null) {
onFrameAnimationListener.onEnd();//触发动画停止回调
}
handler.removeCallbacks(runnable);
}
/**
* 重写开始方法监听动画是否结束
*/
@Override
public void start() {
super.start();
initHandler();
if (onFrameAnimationListener != null) {
onFrameAnimationListener.onStart();//触发动画开始回调
}
}
private void initHandler() {
handler.postDelayed(runnable, maxDuration == 0 ? getMaxDuration() : maxDuration);
}
@Override
public void stop() {
super.stop();
}
/**
* 获取持续时间最长的帧的持续时间
*
* @return 时间 如果这一帧大于1秒,则返回 1 秒,否则返回这一帧的持续时间
*/
private int getMaxDuration() {
for (int i = 0; i < this.getNumberOfFrames(); i++) {
if (maxDuration < getDuration(i)) {
maxDuration = getDuration(i);
}
}
return maxDuration > 1000 ? 1000 : maxDuration;
}
/**
* 设置动画监听器
*
* @param onFrameAnimationListener 监听器
*/
public void setOnFrameAnimationListener(OnFrameAnimationListener onFrameAnimationListener) {
this.onFrameAnimationListener = onFrameAnimationListener;
}
/**
* 动画监听器
*/
public interface OnFrameAnimationListener {
/**
* 动画开始
*/
void onStart();
/**
* 动画结束
*/
void onEnd();
}
}
使用方法
MyFrameAnimation animation = new MyFrameAnimation();
animation.setOnFrameAnimationListener(new MyFrameAnimation.OnFrameAnimationListener() {
@Override
public void onStart() {
}
@Override
public void onEnd() {
}
});
//获取各种drawable
Drawable drawable = ContextCompat.getDrawable(this,R.mipmap.ic_launcher);
//添加单帧
animation.addFrame(drawable,300);
animation.addFrame(drawable,300);
animation.addFrame(drawable,300);
animation.addFrame(drawable,300);
//设置给ImageView
imageView.setImageDrawable(animation);
//开始帧动画
animation.start();