public class AnimView extends View {
private final String TAG = AnimView.class.getCanonicalName();
private final int INVALIDATE = 0x0023;
private HandlerThread thread;
private Handler handler;
private int width = 0;
private int height = 0;
private String animFilePath;
private String[] animFileList;
private int index;
private int repeatIndex;
private Bitmap bitmap;
private String defaultPath;
private String currentPath;
private final Object lock = new Object();
private boolean isRunning;
private boolean isPrepare;
private boolean isOneShot;
private int time;
private OnAnimationFinishListener listener;
private Handler callbackHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case INVALIDATE:
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.width = bitmap.getWidth();
layoutParams.height = bitmap.getHeight();
setLayoutParams(layoutParams);
break;
}
return false;
}
});
public AnimView(Context context) {
super(context);
}
public AnimView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AnimView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void init() {
repeatIndex = 0;
isRunning = false;
isOneShot = true;
time = 83;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
init();
if (thread == null) {
thread = new HandlerThread(TAG);
thread.start();
handler = new Handler(thread.getLooper());
}
synchronized (lock) {
isPrepare = true;
if (isRunning) {
handler.post(animRunnable);
} else if (defaultPath != null) {
drawableDefault();
}
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
isPrepare = false;
stop();
handler.removeCallbacks(animRunnable);
}
public void setDefaultPath(String path) {
defaultPath = path;
drawableDefault();
}
private void drawableDefault() {
currentPath = defaultPath;
postInvalidate();
}
public void start(String path) {
if (this.animFilePath == null || !this.animFilePath.equals(path)) {
stop();
this.animFilePath = path;
animFileList = AssetsUtil.getAssetsFileList(getContext(), path);
repeatIndex = 0;
}
synchronized (lock) {
index = 0;
if (isRunning == true) {
return;
}
isRunning = true;
if (isPrepare) {
handler.removeCallbacks(animRunnable);
handler.post(animRunnable);
}
}
}
public void stop() {
synchronized (lock) {
isRunning = false;
}
}
public String getAnimFilePath() {
return animFilePath;
}
public boolean isRunning() {
return isRunning;
}
public void setOneShot(boolean oneShot) {
this.isOneShot = oneShot;
}
public void setTime(int time) {
this.time = time;
}
public void setRepeatIndex(int index) {
repeatIndex = index;
}
public void setAnimationFinishListener(OnAnimationFinishListener listener) {
this.listener = listener;
}
@Override
protected void onDraw(Canvas c) {
super.onDraw(c);
if (bitmap != null) {
if (!bitmap.isRecycled()) {
bitmap.recycle();
}
bitmap = null;
}
if (c != null) {
bitmap = AssetsUtil.readBitmapFromAssets(getContext(), currentPath, Bitmap.Config.ARGB_8888);
c.drawBitmap(bitmap, 0, 0, null);
if (bitmap != null) {
if (width == 0 || height == 0
|| width != bitmap.getWidth() || height != bitmap.getHeight()) {
Log.v(TAG, "call measure");
width = bitmap.getWidth();
height = bitmap.getHeight();
callbackHandler.sendEmptyMessage(INVALIDATE);
}
}
}
}
Runnable animRunnable = new Runnable() {
@Override
public void run() {
index = 0;
while (true) {
currentPath = animFileList[index];
postInvalidate();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (lock) {
index++;
if (index >= animFileList.length) {
if (!isOneShot) {
index = repeatIndex;
} else {
isRunning = false;
if (listener != null) {
listener.onAnimationFinish();
}
if (defaultPath != null) {
drawableDefault();
}
break;
}
}
if (!isRunning) {
break;
}
}
}
}
};
public interface OnAnimationFinishListener {
void onAnimationFinish();
}
}
AnimView Android帧动画
最新推荐文章于 2024-03-28 16:15:19 发布