首先,我尝试了很多在Android中制作流畅动画的方法,而我最好的选择可能就是使用AnimationDrawable.。一切都很完美,直到我走出了旧设备上的异常记忆。原因很明显是帧数,在我的例子中是75帧。这就是我如何使用Thread.sleep()、、AsyncTask、和来动画帧的方法。为了避免动画滞后,我使用了Stack,在其中我预加载了前10帧,然后弹出使用过的帧,然后推送一个新的,直到没有更多的帧。一切都比我预期的要好,但唯一的问题是,在动画结束时,最后一帧消失了,我一整天都在敲击我的头,以理解为什么会发生这种情况,但显然没有成功。下面是我调用动画的活动和动画代码所在的文件中的代码。
SplashActivity.java
private void startAnimation() {
gifImageView = (LogoAnimImageView) findViewById(R.id.gifImageView);
gifImageView.setSplashActivityContext(this);
gifImageView.setBackgroundResource(R.drawable.logo_frame_0);
gifImageView.setAnimImageViewListener(new LogoAnimImageView.LogoAnimImageViewInterface() {
@Override
public void animationEnd() {
mAnimationFinished = true;
LoadNextActivity();
}
});
gifImageView.startLogoAnimation();
}LogoAnimImageView.java
public class LogoAnimImageView extends ImageView {
public interface LogoAnimImageViewInterface {
void animationEnd();
}
final Handler mHandler = new Handler();
private Stack<Drawable> mImageStack;
private SplashActivity mSplashActivity;
private LogoAnimImageViewInterface mListener;
private int mFrameIndex;
private int[] mResources = {R.drawable.logo_frame_0,R.drawable.logo_frame_1,R.drawable.logo_frame_2,R.drawable.logo_frame_3,
R.drawable.logo_frame_4,R.drawable.logo_frame_5,R.drawable.logo_frame_6,
R.drawable.logo_frame_7,R.drawable.logo_frame_8,R.drawable.logo_frame_9,R.drawable.logo_frame_10,
R.drawable.logo_frame_11,R.drawable.logo_frame_12,R.drawable.logo_frame_13,R.drawable.logo_frame_14,
R.drawable.logo_frame_15,R.drawable.logo_frame_16,R.drawable.logo_frame_17,R.drawable.logo_frame_18,
R.drawable.logo_frame_19,R.drawable.logo_frame_20,R.drawable.logo_frame_21,R.drawable.logo_frame_22,
R.drawable.logo_frame_23,R.drawable.logo_frame_24,R.drawable.logo_frame_25,R.drawable.logo_frame_26,
R.drawable.logo_frame_27,R.drawable.logo_frame_28,R.drawable.logo_frame_29,R.drawable.logo_frame_30,
R.drawable.logo_frame_31,R.drawable.logo_frame_32,R.drawable.logo_frame_33,R.drawable.logo_frame_34,
R.drawable.logo_frame_35,R.drawable.logo_frame_36,R.drawable.logo_frame_37,R.drawable.logo_frame_38,
R.drawable.logo_frame_39,R.drawable.logo_frame_40,R.drawable.logo_frame_41,R.drawable.logo_frame_42,
R.drawable.logo_frame_43,R.drawable.logo_frame_44,R.drawable.logo_frame_45,R.drawable.logo_frame_46,
R.drawable.logo_frame_47,R.drawable.logo_frame_48,R.drawable.logo_frame_49,R.drawable.logo_frame_50,
R.drawable.logo_frame_51,R.drawable.logo_frame_52,R.drawable.logo_frame_53,R.drawable.logo_frame_54,
R.drawable.logo_frame_55,R.drawable.logo_frame_56,R.drawable.logo_frame_57,R.drawable.logo_frame_58,
R.drawable.logo_frame_59,R.drawable.logo_frame_60,R.drawable.logo_frame_61,R.drawable.logo_frame_62,
R.drawable.logo_frame_63,R.drawable.logo_frame_64,R.drawable.logo_frame_65,R.drawable.logo_frame_66,
R.drawable.logo_frame_67,R.drawable.logo_frame_68,R.drawable.logo_frame_69,R.drawable.logo_frame_70,
R.drawable.logo_frame_71,R.drawable.logo_frame_72,R.drawable.logo_frame_73,R.drawable.logo_frame_74
};
public LogoAnimImageView(Context context) {
super(context);
}
public LogoAnimImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LogoAnimImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void startLogoAnimation() {
mFrameIndex = 10;
mImageStack = new Stack<Drawable>();
for (int i=1;i<=mFrameIndex;i++) {
Drawable drawable = getDrawable(mResources[i]);
mImageStack.push(drawable);
}
mFrameIndex++;
mSplashActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
new LogoAnimOperation().execute((Object)null);
}
});
}
public void setSplashActivityContext(SplashActivity splashActivity) {
this.mSplashActivity = splashActivity;
}
public void setAnimImageViewListener(LogoAnimImageViewInterface listener) {
this.mListener = listener;
}
private Drawable getDrawable(int id) {
Drawable drawable;
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
drawable = mSplashActivity.getDrawable(id);
} else {
drawable = mSplashActivity.getResources().getDrawable(id);
}
return drawable;
}
private class LogoAnimOperation extends AsyncTask<Object,Void,String> {
@Override
protected String doInBackground(Object... params) {
int number=1;
while (mImageStack.size() > 1) {
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
final Drawable drawable = mImageStack.pop();
mSplashActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
LogoAnimImageView.this.setBackground(drawable);
}
else {
LogoAnimImageView.this.setBackgroundDrawable(drawable);
}
if (mFrameIndex < mResources.length) {
Drawable newDrawable = getDrawable(mResources[mFrameIndex]);
mImageStack.push(newDrawable);
mFrameIndex++;
}
}
});
}
return "";
}
@Override
protected void onPostExecute(String s) {
mSplashActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Drawable drawable = getDrawable(R.drawable.logo_frame_74);
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
LogoAnimImageView.this.setBackground(drawable);
}
else {
LogoAnimImageView.this.setBackgroundDrawable(drawable);
}
}
});
mListener.animationEnd();
super.onPostExecute(s);
}
}
}发布于 2016-03-05 19:16:13
...but,唯一的问题是,在动画结束时,最后一帧消失了,我一整天都在敲我的头,以理解为什么会发生这种情况,而且显然没有成功。
问题可能在于你的AsyncTask's onPostExecute(String)
@Override
protected void onPostExecute(String s) {
mSplashActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Drawable drawable = getDrawable(R.drawable.logo_frame_74);
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
LogoAnimImageView.this.setBackground(drawable);
} else {
LogoAnimImageView.this.setBackgroundDrawable(drawable);
}
}
});
mListener.animationEnd();
super.onPostExecute(s);
}onPostExecute(String)将始终在UI线程上被调用。因此,mSplashActivity.runOnUiThread(....)是多余的。runOnUiThread(Runnable),您将发送到UI线程的事件队列。所以,当轮到它时,运行程序就会被执行。但是,mSplashActivity.runOnUiThread(....)调用后的代码可能会在可运行之前执行。因此,在您的mListener.animationEnd()有机会显示R.drawable.logo_frame_74之前,可能会调用R.drawable.logo_frame_74。但是,这不应该发生在你的情况下。如果从UI线程(它是这样的)调用runOnUiThread(Runnable),则不会将Runnable提交到事件队列,而是立即执行。
我怀疑这里真正的问题是动画(R.drawable.logo_frame_74)的最后一帧和下一个活动的启动之间没有任何延迟。也许您可以注释掉对mListener.animationEnd()的调用,以检查动画是在最后一帧还是第二帧结束。
虽然这是一种有趣的方法,也是我以前从未见过的一种方法,但我不得不说,您处理的线程太多了。如果您试图在需要时加载Drawables,有一种更简单的方法:
public class LogoAnimImageView extends ImageView {
....
....
// flag to indicate whether `mNextFrameDrawable` should continue loading the next frame
private boolean mStopAnimating;
// loads the next frame, and calls back to activity when done
private Runnable mNextFrameRunnable = new Runnable() {
@Override
public void run() {
if (!mStopAnimating) {
if (isFinishedAnimating() && mListener != null) {
mListener.animationEnd();
} else { // Load next frame
setViewBg(getNextFrameDrawable());
// Will load the next frame in 40 ms
postDelayed(this, 40L);
}
}
}
};
// This method can be set `public static` and placed in a separate `Utils` class
private void setViewBg(Drawable d) {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
setBackground(drawable);
} else {
setBackgroundDrawable(drawable);
}
}
private Boolean isFinishedAnimating() {
return mFrameIndex >= mResources.length;
}
// returns the next frame's drawable and increments the `mFrameIndex` pointer
private Drawable getNextFrameDrawable() {
return getDrawable(mResources[mFrameIndex++]);
}
// start animating
public void startLogoAnimation() {
mFrameIndex = 0;
mStopAnimating = false;
post(mNextFrameRunnable);
}
// stop animating
public void stopLogoAnimation() {
mStopAnimating = true;
removeCallbacks(mNextFrameRunnable);
}
....
....
}AsyncTask既不需要,也不适合处理这样的场景。
https://stackoverflow.com/questions/35777512
复制相似问题