我想用几个图像文件做一个动画,为此,AnimationDrawable工作得很好.但是,我需要知道动画何时开始以及何时结束(即添加一个类似于Animation.AnimationListener的侦听器).在搜索完答案后,我感觉不到AnimationDrawable不支持听众.
有没有人知道如何在Android上使用监听器创建逐帧图像动画?
Ric*_*cky 45
做了一些阅读后,我想出了这个解决方案.我仍然感到惊讶的是,没有一个侦听器作为AnimationDrawable对象的一部分,但我不想反复传递回调,所以我创建了一个引发onAnimationFinish()方法的抽象类.我希望这可以帮助别人.
自定义动画可绘制类:
public abstract class CustomAnimationDrawableNew extends AnimationDrawable {
/** Handles the animation callback. */
Handler mAnimationHandler;
public CustomAnimationDrawableNew(AnimationDrawable aniDrawable) {
/* Add each frame to our animation drawable */
for (int i = 0; i < aniDrawable.getNumberOfFrames(); i++) {
this.addFrame(aniDrawable.getFrame(i), aniDrawable.getDuration(i));
}
}
@Override
public void start() {
super.start();
/*
* Call super.start() to call the base class start animation method.
* Then add a handler to call onAnimationFinish() when the total
* duration for the animation has passed
*/
mAnimationHandler = new Handler();
mAnimationHandler.post(new Runnable() {
@Override
public void run() {
onAnimationStart();
}
};
mAnimationHandler.postDelayed(new Runnable() {
@Override
public void run() {
onAnimationFinish();
}
}, getTotalDuration());
}
/**
* Gets the total duration of all frames.
*
* @return The total duration.
*/
public int getTotalDuration() {
int iDuration = 0;
for (int i = 0; i < this.getNumberOfFrames(); i++) {
iDuration += this.getDuration(i);
}
return iDuration;
}
/**
* Called when the animation finishes.
*/
public abstract void onAnimationFinish();
/**
* Called when the animation starts.
*/
public abstract void onAnimationStart();
}
Run Code Online (Sandbox Code Playgroud)
要使用此类:
ImageView iv = (ImageView) findViewById(R.id.iv_testing_testani);
iv.setOnClickListener(new OnClickListener() {
public void onClick(final View v) {
// Pass our animation drawable to our custom drawable class
CustomAnimationDrawableNew cad = new CustomAnimationDrawableNew(
(AnimationDrawable) getResources().getDrawable(
R.drawable.anim_test)) {
@Override
void onAnimationStart() {
// Animation has started...
}
@Override
void onAnimationFinish() {
// Animation has finished...
}
};
// Set the views drawable to our custom drawable
v.setBackgroundDrawable(cad);
// Start the animation
cad.start();
}
});
Run Code Online (Sandbox Code Playgroud)
ben*_*lau 25
我需要知道我的一次性AnimationDrawable何时完成,而不必继承AnimationDrawable子类,因为我必须在XML中设置动画列表.我写了这个课,并在Gingerbread和ICS上进行了测试.可以轻松扩展它以在每个帧上进行回调.
/**
* Provides a callback when a non-looping {@link AnimationDrawable} completes its animation sequence. More precisely,
* {@link #onAnimationComplete()} is triggered when {@link View#invalidateDrawable(Drawable)} has been called on the
* last frame.
*
* @author Benedict Lau
*/
public abstract class AnimationDrawableCallback implements Callback {
/**
* The last frame of {@link Drawable} in the {@link AnimationDrawable}.
*/
private Drawable mLastFrame;
/**
* The client's {@link Callback} implementation. All calls are proxied to this wrapped {@link Callback}
* implementation after intercepting the events we need.
*/
private Callback mWrappedCallback;
/**
* Flag to ensure that {@link #onAnimationComplete()} is called only once, since
* {@link #invalidateDrawable(Drawable)} may be called multiple times.
*/
private boolean mIsCallbackTriggered = false;
/**
*
* @param animationDrawable
* the {@link AnimationDrawable}.
* @param callback
* the client's {@link Callback} implementation. This is usually the {@link View} the has the
* {@link AnimationDrawable} as background.
*/
public AnimationDrawableCallback(AnimationDrawable animationDrawable, Callback callback) {
mLastFrame = animationDrawable.getFrame(animationDrawable.getNumberOfFrames() - 1);
mWrappedCallback = callback;
}
@Override
public void invalidateDrawable(Drawable who) {
if (mWrappedCallback != null) {
mWrappedCallback.invalidateDrawable(who);
}
if (!mIsCallbackTriggered && mLastFrame != null && mLastFrame.equals(who.getCurrent())) {
mIsCallbackTriggered = true;
onAnimationComplete();
}
}
@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
if (mWrappedCallback != null) {
mWrappedCallback.scheduleDrawable(who, what, when);
}
}
@Override
public void unscheduleDrawable(Drawable who, Runnable what) {
if (mWrappedCallback != null) {
mWrappedCallback.unscheduleDrawable(who, what);
}
}
//
// Public methods.
//
/**
* Callback triggered when {@link View#invalidateDrawable(Drawable)} has been called on the last frame, which marks
* the end of a non-looping animation sequence.
*/
public abstract void onAnimationComplete();
}
Run Code Online (Sandbox Code Playgroud)
以下是如何使用它.
AnimationDrawable countdownAnimation = (AnimationDrawable) mStartButton.getBackground();
countdownAnimation.setCallback(new AnimationDrawableCallback(countdownAnimation, mStartButton) {
@Override
public void onAnimationComplete() {
// TODO Do something.
}
});
countdownAnimation.start();
Run Code Online (Sandbox Code Playgroud)
Rus*_*hyn 22
可以通过覆盖AnimationDrawable类中的selectDrawable方法轻松跟踪动画结束.完整代码如下:
public class AnimationDrawable2 extends AnimationDrawable
{
public interface IAnimationFinishListener
{
void onAnimationFinished();
}
private boolean finished = false;
private IAnimationFinishListener animationFinishListener;
public IAnimationFinishListener getAnimationFinishListener()
{
return animationFinishListener;
}
public void setAnimationFinishListener(IAnimationFinishListener animationFinishListener)
{
this.animationFinishListener = animationFinishListener;
}
@Override
public boolean selectDrawable(int idx)
{
boolean ret = super.selectDrawable(idx);
if ((idx != 0) && (idx == getNumberOfFrames() - 1))
{
if (!finished)
{
finished = true;
if (animationFinishListener != null) animationFinishListener.onAnimationFinished();
}
}
return ret;
}
}
Run Code Online (Sandbox Code Playgroud)
hit*_*h45 16
我使用了一个递归函数来检查当前帧是否是每次检查毫秒的最后一帧.
private void checkIfAnimationDone(AnimationDrawable anim){
final AnimationDrawable a = anim;
int timeBetweenChecks = 300;
Handler h = new Handler();
h.postDelayed(new Runnable(){
public void run(){
if (a.getCurrent() != a.getFrame(a.getNumberOfFrames() - 1)){
checkIfAnimationDone(a);
} else{
Toast.makeText(getApplicationContext(), "ANIMATION DONE!", Toast.LENGTH_SHORT).show();
}
}
}, timeBetweenChecks);
}
Run Code Online (Sandbox Code Playgroud)
我猜你的代码不起作用,因为你尝试从非 UI 线程修改视图。尝试从您的活动中调用 runOnUiThread(Runnable) 。我用它在菜单的动画完成后淡出菜单。这段代码对我有用:
Animation ani = AnimationUtils.loadAnimation(YourActivityNameHere.this, R.anim.fadeout_animation);
menuView.startAnimation(ani);
// Use Timer to set visibility to GONE after the animation finishes.
TimerTask timerTask = new TimerTask(){
@Override
public void run() {
YourActivityNameHere.this.runOnUiThread(new Runnable(){
@Override
public void run() {
menuView.setVisibility(View.GONE);
}
});}};
timer.schedule(timerTask, ani.getDuration());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
41759 次 |
| 最近记录: |