gpt4 book ai didi

android - 通过使用计时器(或处理程序)更改 ImageView 中的图像来创建动画

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:26:49 25 4
gpt4 key购买 nike

我想通过更改 ImageView 中的帧来创建一个简单的动画。我不想使用 AnimationDrawable,因为我需要在帧更改或动画停止时接收事件,以便能够向后播放、重新启动等等。

我的问题是尽管 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 对象,在我的 Activity 中我通过 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 可以解决您的问题:http://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html

Drawable[] layers = new Drawable[2];
layers[0] = //your first drawable
layers[1] = //your second drawable
TransitionDrawable transition = new TransitionDrawable(layers);
myImageView.setImageDrawable(transition);
transition.startTransition(1500);

关于android - 通过使用计时器(或处理程序)更改 ImageView 中的图像来创建动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19146337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com