5
我想通過更改ImageView中的框架來創建簡單的動畫。我不想使用AnimationDrawable,因爲當幀更改或動畫停止時,需要接收事件以便能夠向後播放,重新啓動等等。使用Timer(或Handler)在ImageView中更改圖像來創建動畫
我的問題是,雖然setImageDrawable被調用(在主線程上),但幀實際上並沒有改變事件。所以一切似乎都很好,除了幀不會改變(實際上只是一個畫框,第一個)。
所以我的代碼:
public class AnimatedImageView extends ImageView implements Animatable, Runnable {
private static final String TAG = "AnimatedImageView";
public static interface AnimationEventsListener {
void animationDidChangeFrame(AnimatedImageView animatedImageView);
void animationDidStop(AnimatedImageView animatedImageView);
}
/* frames - ress ids */
private int[] mFrameResIds;
/* current frame index */
private int mCurrentFrameIdx;
/* number of the current repeat */
private int loopIndex;
/* number of animation repetiotions, 0 for infinite */
private int mNumOfRepetitions;
/* if animation is playing */
private boolean playing;
/* if animation is paused */
private boolean paused;
/* if animation is playing backward */
private boolean playItBackward;
/* animation duration */
private long mAnimationDuration;
/* frame animation duration (mAnimationDuration/num_of_frames) */
private long mFrameAnimationDuration;
/* listener for animation events */
private AnimationEventsListener mListener;
private Handler mHandler;
public AnimatedImageView(Context context) {
super(context);
setup();
}
public AnimatedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public AnimatedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
mHandler = new Handler(Looper.getMainLooper());
this.setClickable(true);
Logger.d("MSG", "setup, thread: " + Thread.currentThread().toString());
}
@Override
public void start() {
if (playing) {
return;
}
mCurrentFrameIdx = playItBackward ? mFrameResIds.length - 1 : 0;
loopIndex = 0;
playing = true;
updateFrame();
}
@Override
public void stop() {
paused = true;
}
public void resume() {
paused = false;
playing = true;
updateFrame();
}
@Override
public boolean isRunning() {
return false;
}
@Override
public void run() {
Logger.d("MSG", "run, thread: " + Thread.currentThread().toString());
updateFrame();
}
public AnimationEventsListener getListener() {
return mListener;
}
public void setListener(AnimationEventsListener mListener) {
this.mListener = mListener;
}
public long getAnimationDuration() {
return mAnimationDuration;
}
public void setAnimationDuration(long mAnimationDuration) {
this.mAnimationDuration = mAnimationDuration;
if (mFrameResIds != null) {
mFrameAnimationDuration = mAnimationDuration/mFrameResIds.length;
}
}
public int[] getFrameResIds() {
return mFrameResIds;
}
public void setFrameResIds(int[] mFrameResIds) {
this.mFrameResIds = mFrameResIds;
if (mFrameResIds != null) {
mFrameAnimationDuration = mAnimationDuration/mFrameResIds.length;
}
}
private void setCurrentFrame(int frameValue) {
mCurrentFrameIdx = frameValue;
this.setAnimationFrame(frameValue);
}
private void setAnimationFrame(int animationFrame) {
Logger.d("MSG", "setAnimationFrame: " + animationFrame);
if (animationFrame < 0) {
animationFrame = 0;
}
if (animationFrame > -1) {
animationFrame = mFrameResIds.length - 1;
}
Resources resources = getResources();
AnimatedImageView.this.setImageDrawable(resources.getDrawable(mFrameResIds[animationFrame]));
AnimatedImageView.this.forceLayout();
// AnimatedImageView.this.setImageBitmap(BitmapFactory.decodeResource(resources, mFrameResIds[animationFrame]));
// this.setImageResource(mFrameResIds[animationFrame]);
AnimatedImageView.this.invalidate();
}
private void updateFrame() {
Logger.d("MSG", "updateFrame " + mCurrentFrameIdx);
if (!playing || paused) {
return;
}
playing = false;
if (mListener != null) {
mListener.animationDidChangeFrame(AnimatedImageView.this);
}
if (!playItBackward) {
mCurrentFrameIdx++;
if (mCurrentFrameIdx >= mFrameResIds.length) {
loopIndex++;
mCurrentFrameIdx = 0;
if (mNumOfRepetitions == loopIndex) {
if (mListener != null) {
mListener.animationDidStop(AnimatedImageView.this);
}
return;
}
}
} else {
mCurrentFrameIdx--;
if (mCurrentFrameIdx < 0) {
loopIndex++;
mCurrentFrameIdx = mFrameResIds.length - 1;
if (mNumOfRepetitions == loopIndex) {
if (mListener != null) {
mListener.animationDidStop(AnimatedImageView.this);
}
return;
}
}
}
playing = true;
setAnimationFrame(mCurrentFrameIdx);
// mHandler.postDelayed(AnimatedImageView.this, mFrameAnimationDuration);
// scheduleDrawable(getResources().getDrawable(mFrameResIds[mCurrentFrameIdx]), AnimatedImageView.this, mFrameAnimationDuration);
// postDelayed()
postDelayed(AnimatedImageView.this, mFrameAnimationDuration);
// SongPlayerActivity.handler.postDelayed(AnimatedImageView.this, mFrameAnimationDuration);
}
我有我的XML和我在活動佈局的AnimatedImageView對象我的ID找到它,並開始點擊動畫:
final AnimatedImageView mDriverAnimation = (AnimatedImageView) findViewById(R.id.driver);
mDriverAnimation.setFrameResIds(new int[]{R.drawable.song1_driver1, R.drawable.song1_driver2, R.drawable.song1_driver3});
mDriverAnimation.setAnimationDuration(3 * 1000);
mDriverAnimation.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mDriverAnimation.start();
}
});
任何想法? :) 謝謝。
不是真的,我希望能夠手動更改的框架,所以我可以打電話給我的聽衆。如果我使用TransitionDrawable,我仍然不會在每幀後通知。感謝您的回答 – laurentiugh