最近在做幀動(dòng)畫,由于AnimationDrawable其實(shí)就是個(gè)Drawable,本身并沒有監(jiān)聽,研究了很多方法,網(wǎng)上的方法都是通過啟動(dòng)一個(gè)Handler,延時(shí)停止動(dòng)畫,這種方法雖然能實(shí)現(xiàn),但是有個(gè)很大的問題,就是假如機(jī)器卡頓,那么動(dòng)畫就和Handler不同步了,動(dòng)畫持續(xù)時(shí)間越長,這個(gè)問題就越嚴(yán)重,于是各種查找方法,最后在API中發(fā)現(xiàn)了一行沒有注釋的代碼,對(duì),就是沒有注釋,結(jié)果就讓我忽略的方法
getCurrent() 獲取當(dāng)前幀,得到的是一個(gè) Drawable
然后想到能夠獲取指定幀的 Drawable,那么我們直接拿到最后一幀的 Drawable和當(dāng)前幀做比較不就行了?就是如此
getFrame(int i) 獲取指定幀的 Drawable
getNumberOfFrames() 獲取總幀數(shù)
最終組合成核心代碼
getFrame(getNumberOfFrames() -1) != getCurrent()
最后自定義個(gè)接口來實(shí)現(xiàn)監(jiān)聽就搞定啦
/**
* 作 者:MrYan (QQ:416643088)
* 創(chuàng)建日期:8/6 0006.
* 帶回調(diào)的幀動(dòng)畫
*/
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() {
//獲取最后一幀,和當(dāng)前幀做比較,如果相等,就結(jié)束動(dòng)畫,調(diào)用動(dòng)畫結(jié)束回調(diào)
if (getFrame(getNumberOfFrames() - 1) != getCurrent()) {
initHandler(); //如果不是最后一幀,重新啟動(dòng)handler
} else {
unRunning(); //如果是最后一幀,觸發(fā)結(jié)束回調(diào)
}
}
};
}
/**
* 動(dòng)畫不在運(yùn)行,觸發(fā)結(jié)束回調(diào)
*/
private void unRunning() {
if (onFrameAnimationListener != null) {
onFrameAnimationListener.onEnd();//觸發(fā)動(dòng)畫停止回調(diào)
}
handler.removeCallbacks(runnable);
}
/**
* 重寫開始方法監(jiān)聽動(dòng)畫是否結(jié)束
*/
@Override
public void start() {
super.start();
initHandler();
if (onFrameAnimationListener != null) {
onFrameAnimationListener.onStart();//觸發(fā)動(dòng)畫開始回調(diào)
}
}
private void initHandler() {
handler.postDelayed(runnable, maxDuration == 0 ? getMaxDuration() : maxDuration);
}
@Override
public void stop() {
super.stop();
}
/**
* 獲取持續(xù)時(shí)間最長的幀的持續(xù)時(shí)間
*
* @return 時(shí)間 如果這一幀大于1秒,則返回 1 秒,否則返回這一幀的持續(xù)時(shí)間
*/
private int getMaxDuration() {
for (int i = 0; i < this.getNumberOfFrames(); i++) {
if (maxDuration < getDuration(i)) {
maxDuration = getDuration(i);
}
}
return maxDuration > 1000 ? 1000 : maxDuration;
}
/**
* 設(shè)置動(dòng)畫監(jiān)聽器
*
* @param onFrameAnimationListener 監(jiān)聽器
*/
public void setOnFrameAnimationListener(OnFrameAnimationListener onFrameAnimationListener) {
this.onFrameAnimationListener = onFrameAnimationListener;
}
/**
* 動(dòng)畫監(jiān)聽器
*/
public interface OnFrameAnimationListener {
/**
* 動(dòng)畫開始
*/
void onStart();
/**
* 動(dòng)畫結(jié)束
*/
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);
//設(shè)置給ImageView
imageView.setImageDrawable(animation);
//開始幀動(dòng)畫
animation.start();