首先,我嘗試了很多方法在Android中製作流暢的動畫,可能我最好的選擇是使用AnimationDrawable。在舊設備上出現內存異常之前,一切都是完美的。原因很明顯是幀數,在我的情況下是75.這就是我如何使用AsyncTask和Thread.sleep()來動畫幀。爲了避免動畫滯後,我使用了一個Stack,其中我預加載了前10幀,然後彈出使用過的一個,並推入新的一個,直到沒有更多的幀。一切都比我預期的更好,但唯一的問題是,在動畫結束時,最後一幀消失了,我整天都在摸索着理解爲什麼這樣的事情顯然沒有成功。以下是我在其中調用動畫的活動以及動畫代碼所在的文件中的代碼。Android異步任務框架動畫
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);
}
}
}
我試過你的解決方案,它的效果很好。唯一的問題是動畫不是很流暢。你認爲使用帶預裝drawable的堆棧可以幫助提高動畫的性能嗎? – axel
@axel對不起,我一直忙於完成一個項目。自那以後我沒有登錄過。爲了順利進行,我們需要從一幀轉換到下一幀。而不是調用'setViewBg(getNextFrameDrawable()); 'mNextFrameRunnable'內,我們可以使用一個持續時間爲35毫秒的'TransitionDrawable'來實現這種平滑。我真的希望你能夠挖掘一些其他資源來獲得答案。如果沒有,我可以用添加的轉換位更新答案。 – Vikram