From 0f0079dea0025a4b7d8447525c35db989aa79d49 Mon Sep 17 00:00:00 2001 From: seven332 Date: Mon, 26 Jan 2015 23:36:03 +0800 Subject: [PATCH] Improve scene --- app/src/main/java/com/hippo/scene/Scene.java | 34 ++-- .../java/com/hippo/scene/StageActivity.java | 149 +++++++++++++----- 2 files changed, 128 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index 7a7410cfc..f882ce8e9 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -30,7 +30,7 @@ public abstract class Scene { private StageActivity mStageActivity; private FrameLayout mStageView; - private View mRootViewOfScence; + private View mRootView; void setStageActivity(StageActivity stageActivity) { mStageActivity = stageActivity; @@ -38,37 +38,40 @@ public abstract class Scene { } public void setContentView(int layoutResID) { - mRootViewOfScence = mStageActivity.getLayoutInflater() + mRootView = mStageActivity.getLayoutInflater() .inflate(layoutResID, mStageView, false); } public void setContentView(View view) { - mRootViewOfScence = view; + mRootView = view; } public View findViewById(int id) { AssertUtils.assertNotNull("Call setContentView before findViewById", - mRootViewOfScence); + mRootView); - return mRootViewOfScence.findViewById(id); + return mRootView.findViewById(id); } - - public void startScene(Class sceneClass) { - mStageActivity.pushScene(sceneClass); + View getRootView() { + return mRootView; } - private void addToStage() { + public void startScene(Class sceneClass) { + mStageActivity.startScene(this, sceneClass); + } + public final void finish() { + mStageActivity.finishScene(this); } void create() { onCreate(); AssertUtils.assertNotNull("You have to call setContentView in onCreate", - mRootViewOfScence); + mRootView); - mStageActivity.addScenseView(mRootViewOfScence); + mStageActivity.addSceneView(this); } void pause() { @@ -98,14 +101,7 @@ public abstract class Scene { * This method should be called to remove when it need to remove */ public final void dispatchRemove() { - mStageActivity.removeScenseView(mRootViewOfScence); - } - - /** - * This method should be called to remove when it need to hide - */ - public final void dispatchHide() { - mStageActivity.removeScenseView(mRootViewOfScence); + mStageActivity.stopSceneRetain(this); } } diff --git a/app/src/main/java/com/hippo/scene/StageActivity.java b/app/src/main/java/com/hippo/scene/StageActivity.java index a9a6715c2..db3d42334 100644 --- a/app/src/main/java/com/hippo/scene/StageActivity.java +++ b/app/src/main/java/com/hippo/scene/StageActivity.java @@ -15,7 +15,6 @@ package com.hippo.scene; -import android.view.View; import android.widget.FrameLayout; import com.hippo.ehviewer.ui.AbsActionBarActivity; @@ -26,12 +25,14 @@ import java.util.Stack; public abstract class StageActivity extends AbsActionBarActivity { private Stack mSceneStack = new Stack<>(); - private LinkedList mScenseAction = new LinkedList<>(); + private LinkedList mScenseActionQueue = new LinkedList<>(); private Scene mCurrentScene = null; + private Scene mRetainedScene = null; + public abstract FrameLayout getStageView(); - protected void pushScene(Class sceneClass) { + private void pushScene(Class sceneClass) { Scene scene = null; try { scene = (Scene) sceneClass.newInstance(); @@ -46,60 +47,136 @@ public abstract class StageActivity extends AbsActionBarActivity { scene.setStageActivity(this); - Scene lastScence = mCurrentScene; + Scene lastScene = mCurrentScene; mCurrentScene = scene; - if (lastScence != null) { + if (lastScene != null) { // It is not the first scense - mSceneStack.push(lastScence); - lastScence.pause(); + mSceneStack.push(lastScene); + + mRetainedScene = lastScene; + lastScene.pause(); } mCurrentScene.create(); } - public void popScense() { + private void popScense() { if (mSceneStack.isEmpty()) { - // TODO Should finish now ? + // It is the last scene + mRetainedScene = mCurrentScene; + mCurrentScene.destroy(); } else { - Scene previousScence = mCurrentScene; + Scene previousScene = mCurrentScene; mCurrentScene = mSceneStack.pop(); - previousScence.onDestroy(); - mCurrentScene.onResume(); + mRetainedScene = previousScene; + previousScene.destroy(); + mCurrentScene.resume(); } } - void removeScenseView(View view) { - getStageView().removeView(view); + void addSceneView(Scene scene) { + if (scene != mCurrentScene) { + throw new IllegalStateException("This scene should be current scene."); + } + + getStageView().addView(scene.getRootView()); } - void addScenseView(View view) { - getStageView().addView(view); + void stopSceneRetain(Scene scene) { + if (mRetainedScene == null) { + throw new IllegalStateException("Do not call dispatchRemove more than " + + "once."); + } + if (mRetainedScene != scene) { + throw new IllegalStateException("Only call dispatchRemove in onPause " + + "and onDestroy"); + } + + Scene retainScene = mRetainedScene; + mRetainedScene = null; + getStageView().removeView(scene.getRootView()); + + if (retainScene == mCurrentScene) { + // No need to handle scene action + mScenseActionQueue.clear(); + // It is the last scene, let's finish the activity. + finish(); + } else { + // Handle SceneAction + if (!mScenseActionQueue.isEmpty()) { + mScenseActionQueue.poll().doAction(); + } + } } + void startScene(Scene fromScene, Class sceneClass) { + if (mRetainedScene == null) { + // No retained scene, no animation + if (fromScene == mCurrentScene) { + // Only current scene can start new scene. + // If not, just miss it. + pushScene(sceneClass); + } + } else { + mScenseActionQueue.offer(new StartSceneAction(fromScene, sceneClass)); + } + } + + void finishScene(Scene scene) { + if (scene != mRetainedScene && scene != mCurrentScene) { + // Remove with out animation + getStageView().removeView(scene.getRootView()); + mSceneStack.remove(scene); + } else { + if (mRetainedScene == null) { + // Because scene can't be null, so scene == mCurrentScene + popScense(); + } else { + mScenseActionQueue.offer(new FinishSceneAction(scene)); + } + } + } + + @Override public void onBackPressed() { - // TODO super.onBackPressed(); - } - - - - interface ScenseAction { - public void doAction(); - } - - class PushScenseAction implements ScenseAction { - @Override - public void doAction() { - - } - } - - class PopScenseAction implements ScenseAction { - - @Override - public void doAction() { + if (mRetainedScene == null) { + // No retained scene, no animation + // If not, just miss it. popScense(); } } + interface SceneAction { + public void doAction(); + } + + class StartSceneAction implements SceneAction { + private Scene mFromScene; + private Class mSceneClass; + + public StartSceneAction(Scene fromScene, Class sceneClass) { + mFromScene = fromScene; + mSceneClass = sceneClass; + } + + @Override + public void doAction() { + startScene(mFromScene, mSceneClass); + } + } + + class FinishSceneAction implements SceneAction { + private Scene mScene; + + public FinishSceneAction(Scene scene) { + mScene = scene; + } + + @Override + public void doAction() { + finishScene(mScene); + } + } + }