diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 824af45da..80ab2fe82 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -21,7 +21,6 @@ import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; -import android.os.Bundle; import android.os.Parcelable; import android.provider.MediaStore; import android.support.annotation.NonNull; @@ -64,8 +63,8 @@ public class GalleryListScene extends Scene implements SearchLayout.SearhLayoutH @SuppressLint("InflateParams") @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public void onCreate() { + super.onCreate(); mActivity = (ContentActivity) getStageActivity(); mResources = mActivity.getResources(); diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/TestScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/TestScene.java index 805e77072..4fecac8b9 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/TestScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/TestScene.java @@ -16,7 +16,6 @@ package com.hippo.ehviewer.ui.scene; import android.content.res.Resources; -import android.os.Bundle; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ui.ContentActivity; @@ -28,8 +27,8 @@ public class TestScene extends Scene { private Resources mResources; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public void onCreate() { + super.onCreate(); setContentView(R.layout.scene_test); mActivity = (ContentActivity) getStageActivity(); diff --git a/app/src/main/java/com/hippo/scene/Curtain.java b/app/src/main/java/com/hippo/scene/Curtain.java index 47c950b69..c6fc67de1 100644 --- a/app/src/main/java/com/hippo/scene/Curtain.java +++ b/app/src/main/java/com/hippo/scene/Curtain.java @@ -16,9 +16,24 @@ package com.hippo.scene; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; public abstract class Curtain { + private int mPreviousSceneCode; + + void setPreviousScene(@Nullable Scene pScene) { + if (pScene == null) { + mPreviousSceneCode = -1; + } else { + mPreviousSceneCode = pScene.hashCode(); + } + } + + boolean isPreviousScene(@Nullable Scene scene) { + return scene != null && scene.hashCode() == mPreviousSceneCode; + } + /** * Called when * @@ -40,10 +55,10 @@ public abstract class Curtain { public abstract boolean isInAnimation(); protected void dispatchOpenFinished(@NonNull Scene enter, @NonNull Scene exit) { - + exit.openFinished(); } protected void dispatchCloseFinished(@NonNull Scene enter, @NonNull Scene exit) { - exit.detachFromeStage(); + exit.closeFinished(); } } diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index ce25fee43..49405fd45 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -44,11 +44,13 @@ public abstract class Scene { static final int SCENE_STATE_CLOSE = 4; static final int SCENE_STATE_PAUSE = 5; + private @Nullable Curtain mCurtain; + private @Nullable FrameLayout mSceneView; private int mBackgroundColor = 0xffeeeeee; // TODO Need a better to set background color - private int mState = SCENE_STATE_CREATE; + private int mState; private static SceneManager sSceneManager; @@ -56,6 +58,14 @@ public abstract class Scene { sSceneManager = sceneManager; } + void setCurtain(@Nullable Curtain curtain) { + mCurtain = curtain; + } + + @Nullable Curtain getCurtain() { + return mCurtain; + } + // If there is no StageActivity for SceneManager, yout will get AssertError public @NonNull StageActivity getStageActivity() { StageActivity stageActivity = sSceneManager.getStageActivity(); @@ -97,8 +107,8 @@ public abstract class Scene { sSceneManager.finishScene(this); } - void create(Bundle savedInstanceState) { - onCreate(savedInstanceState); + void create() { + onCreate(); if (mSceneView == null) { mSceneView = new FrameLayout(getStageActivity()); @@ -109,29 +119,28 @@ public abstract class Scene { attachToStage(); } - void resume() { - onResume(); + void destroy() { + onDestroy(); + } + + void open() { + onOpen(); + } + + void close() { + onClose(); } void pause() { onPause(); } - void destroy(boolean removeScene) { - onDestroy(); - - if (removeScene) { - // Make sure scene view is detached from stage - detachFromeStage(); - } + void resume() { + onResume(); } - /** - * It is called when scene is created - * - * @param savedInstanceState null for first time, non null for recrearte - */ - protected void onCreate(Bundle savedInstanceState) { + void out() { + onOut(); } public void setBackgroundColor(int bgColor) { @@ -149,8 +158,6 @@ public abstract class Scene { } protected void setContentView(int resId) { - AssertUtils.assertNull("Only call setContentView once", mSceneView); - StageActivity sa = getStageActivity(); mSceneView = new FrameLayout(sa); initBackground(mSceneView); @@ -159,8 +166,6 @@ public abstract class Scene { } protected void setContentView(View view) { - AssertUtils.assertNull("Only call setContentView once", mSceneView); - StageActivity sa = getStageActivity(); mSceneView = new FrameLayout(sa); initBackground(mSceneView); @@ -173,15 +178,26 @@ public abstract class Scene { bg.setClickable(true); } - protected void onResume() { - } - - protected void onPause() { + protected void onCreate() { } protected void onDestroy() { } + protected void onOpen() { + } + + protected void onClose() { + } + + protected void onPause() { + } + + protected void onResume() { + } + + protected void onOut() { + } /** * Finds a view that was identified by the id attribute from the XML that @@ -228,11 +244,6 @@ public abstract class Scene { } } - /* - void attachToStageAsPreScene() { - } - */ - // Remove scene view from stage layout void detachFromeStage() { if (mSceneView != null && isInStage()) { @@ -244,19 +255,29 @@ public abstract class Scene { getStageActivity().attachSceneToStage(this); } - /* - void doAttachToStageAsPreScene() { - getStageActivity().attachSceneToStageAsPreScene(this); - } - */ - void doDetachFromeStage() { getStageActivity().detachSceneFromStage(this); } public void onBackPressed() { // TODO First click to show finish animation, click again to finish the animation at once and it is finished - finish(); + + if (mCurtain != null && mCurtain.isInAnimation()) { + mCurtain.endAnimation(); + } else if (!sSceneManager.endLegacyScene()) { + sSceneManager.finishScene(this); + } + } + + void openFinished() { + open(); + setState(Scene.SCENE_STATE_RUN); + } + + void closeFinished() { + sSceneManager.removeLegacyScene(this); + setState(Scene.SCENE_STATE_DESTROY); + detachFromeStage(); } // It is constant diff --git a/app/src/main/java/com/hippo/scene/SceneManager.java b/app/src/main/java/com/hippo/scene/SceneManager.java index 180d95f25..c174b6a12 100644 --- a/app/src/main/java/com/hippo/scene/SceneManager.java +++ b/app/src/main/java/com/hippo/scene/SceneManager.java @@ -18,7 +18,6 @@ package com.hippo.scene; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.util.Pair; import com.hippo.util.Log; @@ -28,9 +27,11 @@ class SceneManager { private static final String TAG = SceneManager.class.getSimpleName(); - private Stack> mSceneStack = new Stack<>(); + private Stack mSceneStack = new Stack<>(); private StageActivity mStageActivity; + private Scene mLegacyScene; + // Should only be called by SceneApplication SceneManager() { } @@ -43,6 +44,7 @@ class SceneManager { return mStageActivity; } + // TODO check previousState state void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer, @Nullable Curtain curtain) { Scene scene; @@ -56,56 +58,102 @@ class SceneManager { } catch (ClassCastException e) { throw new IllegalStateException(sceneClass.getName() + " can not cast to scene"); } + scene.setCurtain(curtain); Scene previousState = getTopState(); + mSceneStack.push(scene); + + if (curtain != null) { + curtain.setPreviousScene(previousState); + } + if (previousState != null) { previousState.pause(); + scene.setState(Scene.SCENE_STATE_PAUSE); } - mSceneStack.push(new Pair<>(scene, curtain)); + scene.setState(Scene.SCENE_STATE_CREATE); + scene.create(); - scene.create(null); - scene.resume(); - - // Do animation via curtain if (curtain != null && previousState != null) { + scene.setState(Scene.SCENE_STATE_OPEN); curtain.open(scene, previousState); + // Set state run by curtain + } else { + scene.setState(Scene.SCENE_STATE_RUN); } } + boolean endLegacyScene() { + if (mLegacyScene != null) { + Curtain curtain = mLegacyScene.getCurtain(); + if (curtain != null && curtain.isInAnimation()) { + curtain.endAnimation(); + mLegacyScene = null; + return true; + } + } + mLegacyScene = null; + return false; + } + void finishScene(@NonNull Scene scene) { int index = getSceneIndex(scene); if (index >= 0 && index < mSceneStack.size()) { - Pair pair = mSceneStack.remove(index); - Curtain curtain = pair.second; - Scene previousState = getTopState(); - // Do animation via curtain - if (curtain != null) { - scene.destroy(false); + endLegacyScene(); + + if (index == 0) { + // It is the last scene, just finish the activity + mSceneStack.remove(index); + scene.destroy(); + scene.setState(Scene.SCENE_STATE_DESTROY); + getStageActivity().finish(); + } else { + // TODO check scene state + mSceneStack.remove(index); + Scene previousState = getTopState(); if (previousState != null) { + previousState.resume(); + scene.setState(Scene.SCENE_STATE_RUN); + } + + scene.destroy(); + + Curtain curtain = scene.getCurtain(); + if (curtain != null && previousState != null && curtain.isPreviousScene(previousState)) { + scene.setState(Scene.SCENE_STATE_CLOSE); + mLegacyScene = scene; curtain.close(previousState, scene); + // detachFromeStage by curtain + } else { + scene.setState(Scene.SCENE_STATE_DESTROY); + scene.detachFromeStage(); } - } else { - scene.destroy(true); } } else { Log.e(TAG, "The scene is not in stage"); } } + void removeLegacyScene(Scene scene) { + if (mLegacyScene == scene) { + mLegacyScene = null; + } + } + private int getSceneIndex(@NonNull Scene scene) { int size = mSceneStack.size(); while (--size >= 0) { - Pair pair = mSceneStack.get(size); - if (scene.equals(pair.first)) { + if (scene.equals(mSceneStack.get(size))) { return size; } } return -1; } + // TODO What if this scene is closing boolean onBackPressed() { Scene scene = getTopState(); if (scene != null) { @@ -119,36 +167,23 @@ class SceneManager { private Scene getTopState() { if (!mSceneStack.isEmpty()) { - return mSceneStack.peek().first; + return mSceneStack.peek(); } else { return null; } } - /* - private Scene getSecondTopState() { - int secondTopIndex = mSceneStack.size() - 2; - if (secondTopIndex >= 0) { - return mSceneStack.get(secondTopIndex).first; - } else { - return null; - } - } - */ - protected void onSaveInstanceState(Bundle outState) { - for (Pair p : mSceneStack) { - Scene scene = p.first; + for (Scene scene : mSceneStack) { scene.saveInstanceState(outState); } } protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { - for (Pair p : mSceneStack) { - Scene scene = p.first; + for (Scene scene : mSceneStack) { // Recreate - scene.create(savedInstanceState); - scene.resume(); + // TODO might hide sceneView, curtain do it ? + scene.create(); scene.restoreInstanceState(savedInstanceState); } } diff --git a/app/src/main/java/com/hippo/scene/TransitionCurtain.java b/app/src/main/java/com/hippo/scene/TransitionCurtain.java index c1356c83f..a2c23a6d1 100644 --- a/app/src/main/java/com/hippo/scene/TransitionCurtain.java +++ b/app/src/main/java/com/hippo/scene/TransitionCurtain.java @@ -38,6 +38,8 @@ public class TransitionCurtain extends Curtain { private List mAnimList = new LinkedList<>(); + private boolean mClearList = true; + public TransitionCurtain(ViewPair[] viewPairArray) { mViewPairArray = viewPairArray; } @@ -59,12 +61,15 @@ public class TransitionCurtain extends Curtain { colorAnim.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { - mAnimList.clear(); + if (mClearList) { + mAnimList.clear(); + } } }); colorAnim.start(); + mAnimList.add(colorAnim); // Handle transit part @@ -111,7 +116,11 @@ public class TransitionCurtain extends Curtain { yAnim.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { + dispatchOpenFinished(enter, exit); ViewUtils.setVisibility(exitView, View.VISIBLE); + + // Hide previous scene + // TODO remove from stage ? ViewUtils.setVisibility(exit.getSceneView(), View.GONE); } }); @@ -133,8 +142,8 @@ public class TransitionCurtain extends Curtain { } @Override - public void close(@NonNull Scene enter, final @NonNull Scene exit) { - + public void close(final @NonNull Scene enter, final @NonNull Scene exit) { + // Show previous scene ViewUtils.setVisibility(enter.getSceneView(), View.VISIBLE); // Handle background @@ -142,8 +151,20 @@ public class TransitionCurtain extends Curtain { colorAnim.setEvaluator(ArgbEvaluator.getInstance()); colorAnim.setDuration(ANIMATE_TIME); + colorAnim.addListener(new SimpleAnimatorListener() { + @Override + public void onAnimationEnd(Animator animation) { + if (mClearList) { + mAnimList.clear(); + } + } + }); + colorAnim.start(); + mAnimList.add(colorAnim); + + // Handle transit part for (ViewPair pair : mViewPairArray) { final View enterView = pair.getFromView(enter); @@ -180,13 +201,7 @@ public class TransitionCurtain extends Curtain { yAnim.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { - dispatchDetachFromeStage(exit); - ViewUtils.setVisibility(enterView, View.VISIBLE); - } - - @Override - public void onAnimationCancel(Animator animation) { - dispatchDetachFromeStage(exit); + dispatchCloseFinished(enter, exit); ViewUtils.setVisibility(enterView, View.VISIBLE); } }); @@ -196,15 +211,23 @@ public class TransitionCurtain extends Curtain { xAnim.start(); yAnim.start(); + mAnimList.add(scaleXAnim); + mAnimList.add(scaleYAnim); + mAnimList.add(xAnim); + mAnimList.add(yAnim); + // TODO show other part progressively } } @Override public void endAnimation() { + mClearList = false; for (ObjectAnimator oa : mAnimList) { oa.end(); } + mClearList = true; + mAnimList.clear(); } @Override