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