From 41ed55188bc52caa1e52407e6d0c10cdc06ff9ad Mon Sep 17 00:00:00 2001 From: seven332 Date: Sat, 1 Aug 2015 19:03:54 +0800 Subject: [PATCH] Improve Scene --- .../com/hippo/ehviewer/EhApplication.java | 6 + .../gallery/glrenderer/GifTexture.java | 18 +- .../hippo/ehviewer/gallery/ui/GLRootView.java | 4 +- .../hippo/ehviewer/ui/ContentActivity.java | 40 +-- .../ehviewer/ui/scene/GalleryDetailScene.java | 98 ++--- .../ehviewer/ui/scene/GalleryListScene.java | 6 +- .../preference/DownloadSettingsScene.java | 4 +- .../ui/scene/preference/EHSettingsScene.java | 3 +- .../com/hippo/ehviewer/util/Settings.java | 2 +- .../main/java/com/hippo/scene/Curtain.java | 17 +- ...urtain.java => ElementsSharedCurtain.java} | 335 +++++++++--------- .../java/com/hippo/scene/OffsetCurtain.java | 220 ++++++++++++ .../java/com/hippo/scene/RippleCurtain.java | 38 +- app/src/main/java/com/hippo/scene/Scene.java | 54 +-- .../java/com/hippo/scene/SceneManager.java | 59 ++- .../java/com/hippo/scene/SimpleCurtain.java | 159 --------- .../java/com/hippo/scene/SimpleDialog.java | 9 + .../com/hippo/scene/SimpleDialogCurtain.java | 88 +++-- .../java/com/hippo/scene/StageLayout.java | 34 ++ .../java/com/hippo/scene/UnionCurtain.java | 70 ++++ .../preference/PreferenceHeaderScene.java | 3 +- .../com/hippo/widget/GlobalLayoutSet.java | 63 ---- 22 files changed, 746 insertions(+), 584 deletions(-) rename app/src/main/java/com/hippo/scene/{TransitionCurtain.java => ElementsSharedCurtain.java} (56%) create mode 100644 app/src/main/java/com/hippo/scene/OffsetCurtain.java delete mode 100644 app/src/main/java/com/hippo/scene/SimpleCurtain.java create mode 100644 app/src/main/java/com/hippo/scene/UnionCurtain.java delete mode 100644 app/src/main/java/com/hippo/widget/GlobalLayoutSet.java diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index 884577c9a..12a7b5343 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -81,6 +81,12 @@ public class EhApplication extends SceneApplication { // TODO Can't create spider info dir } GallerySpider.init(mEhHttpClient, spiderInfoDir); + + Settings.getImageDownloadLocation().ensureDir(); + Settings.getArchiveDownloadLocation().ensureDir(); + + + Settings.getImageDownloadLocation().listFiles(); } private int getMemoryCacheMaxSize() { diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GifTexture.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GifTexture.java index 646d6c68d..84a3152ba 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GifTexture.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GifTexture.java @@ -22,8 +22,7 @@ import android.util.Log; import com.hippo.ehviewer.gallery.gifdecoder.GifDecoder; -import java.util.concurrent.locks.ReentrantLock; - +// TODO read file to memory or do jni public class GifTexture extends TiledTexture { private static final String TAG = GifTexture.class.getSimpleName(); @@ -33,7 +32,7 @@ public class GifTexture extends TiledTexture { private GifDecoder mGifDecoder; private boolean mRunning = false; - private final ReentrantLock mLock = new ReentrantLock(); + private volatile boolean mDecoding = false; private GifDecodeTask mGifDecodeTask; @@ -61,7 +60,7 @@ public class GifTexture extends TiledTexture { GifDecoder gifDecoder = mGifDecoder; while (mRunning && sUploader != null) { - mLock.lock(); + mDecoding = true; gifDecoder.advance(); Bitmap bitmap = gifDecoder.getNextFrame(); @@ -83,9 +82,14 @@ public class GifTexture extends TiledTexture { if (mLastTime != 0) { delay -= time - mLastTime; } + + + //Say.d(TAG, "time - mLastTime = " + (time - mLastTime)); + //Say.d(TAG, "gifDecoder.getNextDelay() = " + (gifDecoder.getNextDelay())); + mLastTime = time; - mLock.unlock(); + mDecoding = false; if (delay > 5) { try { @@ -124,7 +128,7 @@ public class GifTexture extends TiledTexture { mRunning = false; mGifDecodeTask = null; - if (!mLock.isLocked()) { + if (!mDecoding) { mGifDecoder.resetFrameIndex(); mGifDecoder.advance(); Bitmap bitmap = mGifDecoder.getNextFrame(); @@ -142,7 +146,7 @@ public class GifTexture extends TiledTexture { public void recycle() { mRunning = false; - if (mLock.isLocked()) { + if (mDecoding) { mGifDecodeTask.clearByMyself(); } else { mGifDecoder.clear(); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java b/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java index 819da2e5b..890718ac3 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ui/GLRootView.java @@ -130,7 +130,9 @@ public class GLRootView extends GLSurfaceView // for example CyanogenMod use ro.opengles.surface.rgb565, // so just use default EGLConfigChooser. // And we do not need depth buffer - setEGLConfigChooser(false); + // TODO setEGLConfigChooser(8, 8, 8, 8, 0, 0) or setEGLConfigChooser(false) + setEGLConfigChooser(8, 8, 8, 8, 0, 0); + //setEGLConfigChooser(false); setRenderer(this); // setFormat is done by SurfaceView in SDK 2.3 and newer. //if (ApiHelper.USE_888_PIXEL_FORMAT) { diff --git a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java index c44f36899..fda39012f 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java @@ -36,7 +36,6 @@ import com.hippo.ehviewer.widget.DrawerLeftPanel; import com.hippo.ehviewer.widget.FitStageLayout; import com.hippo.scene.Announcer; import com.hippo.scene.SceneManager; -import com.hippo.scene.SimpleCurtain; import com.hippo.scene.StageActivity; import com.hippo.scene.StageLayout; import com.hippo.vectorold.content.VectorContext; @@ -87,7 +86,7 @@ public final class ContentActivity extends StageActivity break; case DRAWER_LIST_SETTINGS: mDrawerLayout.closeDrawers(); - startScene(MainSettingsScene.class, null, new SimpleCurtain(SimpleCurtain.DIRECTION_BOTTOM)); + startScene(MainSettingsScene.class); break; } @@ -174,41 +173,6 @@ public final class ContentActivity extends StageActivity if (savedInstanceState == null) { startScene(GalleryListScene.class, null); } - - /* - - try { - - BitmapPool bitmapPool = new BitmapPool(); - ByteArrayPool byteArrayPool = new ByteArrayPool(); - GifBitmapProvider gifBitmapProvider = new GifBitmapProvider(bitmapPool, byteArrayPool); - - - File file = new File(Environment.getExternalStorageDirectory(), "00000001.gif"); - UniRandomReadFile randomReadFile = UniRandomReadFile.fromFile(file); - GifHeader gifHeader = new GifHeaderParser().setData(randomReadFile).parseHeader(); - if (gifHeader.getStatus() == GifDecoder.STATUS_OK) { - GifDecoder gifDecoder = new GifDecoder(gifBitmapProvider, gifHeader, randomReadFile); - - - for (int i = 0, n = gifDecoder.getFrameCount(); i < n * 2; i++) { - gifDecoder.advance(); - gifDecoder.getNextFrame().compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(new File(Environment.getExternalStorageDirectory(), String.format("%08d", i) + ".png"))); - } - - - - } - - - - - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - */ - - } @Override @@ -267,7 +231,7 @@ public final class ContentActivity extends StageActivity @Override public void onClickSignIn() { mDrawerLayout.closeDrawers(); - startScene(SignInScene.class, null, new SimpleCurtain(SimpleCurtain.DIRECTION_BOTTOM)); + startScene(SignInScene.class); } @Override diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java index a836d4328..d0ba8d3c3 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java @@ -56,9 +56,11 @@ import com.hippo.ehviewer.widget.RatingView; import com.hippo.miscellaneous.StartActivityHelper; import com.hippo.rippleold.RippleSalon; import com.hippo.scene.Announcer; +import com.hippo.scene.OffsetCurtain; import com.hippo.scene.RippleCurtain; import com.hippo.scene.Scene; import com.hippo.scene.SimpleDialog; +import com.hippo.scene.UnionCurtain; import com.hippo.util.URLImageGetter; import com.hippo.widget.AccurateClick; import com.hippo.widget.AutoWrapLayout; @@ -136,6 +138,48 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, client.execute(request); } + @Override + protected void onCreate(boolean rebirth) { + super.onCreate(rebirth); + setContentView(R.layout.scene_gallery_detail); + + mDetailFrameLayout = (FrameLayout) findViewById(R.id.detail_frame_layout); + + mHeader = (ViewGroup) findViewById(R.id.header); + mThumb = (LoadImageView) mHeader.findViewById(R.id.thumb); + mTitle = (TextView) mHeader.findViewById(R.id.title); + mUploader = (TextView) mHeader.findViewById(R.id.uploader); + mCategory = (TextView) mHeader.findViewById(R.id.category); + + mActionCard = (ViewGroup) findViewById(R.id.action_card); + mRead = mActionCard.findViewById(R.id.read); + mDownload = mActionCard.findViewById(R.id.download); + + mContent = (ViewGroup) findViewById(R.id.content); + mInfo = (ViewGroup) mContent.findViewById(R.id.info); + mLanguage = (TextView) mInfo.findViewById(R.id.language); + mPages = (TextView) mInfo.findViewById(R.id.pages); + mSize = (TextView) mInfo.findViewById(R.id.size); + mPosted = (TextView) mInfo.findViewById(R.id.posted); + mResize = (TextView) mInfo.findViewById(R.id.resize); + mFavoredTimes = (TextView) mInfo.findViewById(R.id.favoredTimes); + mRatingText = (TextSwitcher) mContent.findViewById(R.id.rating_text); + mRating = (RatingView) mContent.findViewById(R.id.rating); + mFavorite = (TextView) mContent.findViewById(R.id.favorite); + mTorrent = (TextView) mContent.findViewById(R.id.torrent); + mShare = (TextView) mContent.findViewById(R.id.share); + mRate = (TextView) mContent.findViewById(R.id.rate); + mTag = (LinearLayout) mContent.findViewById(R.id.tag); + mNoTags = (TextView) mTag.findViewById(no_tags); + mComment = (LinearLayout) mContent.findViewById(R.id.comment); + mCommentMore = (TextView) mContent.findViewById(R.id.comment_more); + mPreviewLayout = (PreviewLayout) mContent.findViewById(R.id.preview); + + mProgressBar = findViewById(R.id.progress_bar); + + mViewTransition = new ViewTransition(mContent, mProgressBar); + } + private void handleAnnouncer(Announcer announcer) { if (announcer == null) { Say.e(TAG, "No announcer in GalleryDetailScene, finish itself"); @@ -211,55 +255,23 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, } else if (ACTION_URL.equals(action)) { } else { - Say.e(TAG, "Unkonwn action " + action); + Say.e(TAG, "GalleryDetailScene: Unkonwn action " + action); finish(); } } @Override - protected void onCreate(boolean rebirth) { - super.onCreate(rebirth); - setContentView(R.layout.scene_gallery_detail); - - mDetailFrameLayout = (FrameLayout) findViewById(R.id.detail_frame_layout); - - mHeader = (ViewGroup) findViewById(R.id.header); - mThumb = (LoadImageView) mHeader.findViewById(R.id.thumb); - mTitle = (TextView) mHeader.findViewById(R.id.title); - mUploader = (TextView) mHeader.findViewById(R.id.uploader); - mCategory = (TextView) mHeader.findViewById(R.id.category); - - mActionCard = (ViewGroup) findViewById(R.id.action_card); - mRead = mActionCard.findViewById(R.id.read); - mDownload = mActionCard.findViewById(R.id.download); - - mContent = (ViewGroup) findViewById(R.id.content); - mInfo = (ViewGroup) mContent.findViewById(R.id.info); - mLanguage = (TextView) mInfo.findViewById(R.id.language); - mPages = (TextView) mInfo.findViewById(R.id.pages); - mSize = (TextView) mInfo.findViewById(R.id.size); - mPosted = (TextView) mInfo.findViewById(R.id.posted); - mResize = (TextView) mInfo.findViewById(R.id.resize); - mFavoredTimes = (TextView) mInfo.findViewById(R.id.favoredTimes); - mRatingText = (TextSwitcher) mContent.findViewById(R.id.rating_text); - mRating = (RatingView) mContent.findViewById(R.id.rating); - mFavorite = (TextView) mContent.findViewById(R.id.favorite); - mTorrent = (TextView) mContent.findViewById(R.id.torrent); - mShare = (TextView) mContent.findViewById(R.id.share); - mRate = (TextView) mContent.findViewById(R.id.rate); - mTag = (LinearLayout) mContent.findViewById(R.id.tag); - mNoTags = (TextView) mTag.findViewById(no_tags); - mComment = (LinearLayout) mContent.findViewById(R.id.comment); - mCommentMore = (TextView) mContent.findViewById(R.id.comment_more); - mPreviewLayout = (PreviewLayout) mContent.findViewById(R.id.preview); - - mProgressBar = findViewById(R.id.progress_bar); - - mViewTransition = new ViewTransition(mContent, mProgressBar); + protected void onBind() { + super.onBind(); handleAnnouncer(getAnnouncer()); } + @Override + protected void onRestore() { + super.onRestore(); + } + @Override protected void onGetFitPaddingBottom(int b) { mDetailFrameLayout.setPadding(0, 0, 0, b); @@ -305,14 +317,16 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, Announcer announcer = new Announcer(); announcer.putExtra(InfoScene.KEY_INFO, mGalleryDetail); startScene(InfoScene.class, announcer, - new RippleCurtain((int) x + position[0], (int) y + position[1])); + new UnionCurtain(new RippleCurtain((int) x + position[0], (int) y + position[1]), + new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM))); } else if (v == mComment) { int[] position = new int[2]; ViewUtils.getLocationInAncestor(mComment, position, getSceneView()); Announcer announcer = new Announcer(); announcer.putExtra(CommentScene.KEY_COMMENTS, mGalleryDetail.comments); startScene(CommentScene.class, announcer, - new RippleCurtain((int) x + position[0], (int) y + position[1])); + new UnionCurtain(new RippleCurtain((int) x + position[0], (int) y + position[1]), + new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM))); } } 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 d42b72bc3..3577b7a0f 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 @@ -66,7 +66,7 @@ import com.hippo.scene.Announcer; import com.hippo.scene.Curtain; import com.hippo.scene.Scene; import com.hippo.scene.SimpleDialog; -import com.hippo.scene.TransitionCurtain; +import com.hippo.scene.ElementsSharedCurtain; import com.hippo.util.AnimationUtils; import com.hippo.widget.FabLayout; import com.hippo.widget.FloatingActionButton; @@ -752,7 +752,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, announcer.setAction(GalleryDetailScene.ACTION_GALLERY_INFO); announcer.putExtra(GalleryDetailScene.KEY_GALLERY_INFO, gi); - Curtain curtain = new TransitionCurtain(new TransitonHelper(position)); + Curtain curtain = new ElementsSharedCurtain(new TransitonHelper(position)); startScene(GalleryDetailScene.class, announcer, curtain); @@ -766,7 +766,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, } } - private class TransitonHelper implements TransitionCurtain.ViewPairSet { + private class TransitonHelper implements ElementsSharedCurtain.ViewPairSet { private int mPosition; diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/DownloadSettingsScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/DownloadSettingsScene.java index 4abb951ca..b1d49d4da 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/DownloadSettingsScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/DownloadSettingsScene.java @@ -34,8 +34,8 @@ public class DownloadSettingsScene extends PreferenceScene implements Preference private static final String KEY_IMAGE_DOWNLOAD_LOACTION = "image_download_location"; private static final String KEY_ARCHIVE_DOWNLOAD_LOACTION = "archive_download_location"; - private static Preference mImagePreference; - private static Preference mArchivePreference; + private Preference mImagePreference; + private Preference mArchivePreference; @Override protected void onCreate(boolean rebirth) { diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/EHSettingsScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/EHSettingsScene.java index 3603c6d18..fd829e92b 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/EHSettingsScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/preference/EHSettingsScene.java @@ -23,7 +23,6 @@ import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.R; import com.hippo.ehviewer.client.EhConfig; import com.hippo.ehviewer.util.Settings; -import com.hippo.scene.SimpleCurtain; import com.hippo.scene.preference.ListPreference; import com.hippo.scene.preference.Preference; import com.hippo.scene.preference.PreferenceCategory; @@ -103,7 +102,7 @@ public final class EHSettingsScene extends PreferenceScene implements Preference public boolean onClick(Preference preference) { String key = preference.getKey(); if (Settings.KEY_EXCLUDED_LANGUAGES.equals(key)) { - startScene(ExcludedLanguagesScene.class, null, new SimpleCurtain(SimpleCurtain.DIRECTION_BOTTOM)); + startScene(ExcludedLanguagesScene.class); return true; } else { return false; diff --git a/app/src/main/java/com/hippo/ehviewer/util/Settings.java b/app/src/main/java/com/hippo/ehviewer/util/Settings.java index 61f62d7c2..6cf01e1b3 100644 --- a/app/src/main/java/com/hippo/ehviewer/util/Settings.java +++ b/app/src/main/java/com/hippo/ehviewer/util/Settings.java @@ -242,7 +242,7 @@ public final class Settings { } catch (Exception e) { e.printStackTrace(); } - return dir != null ? dir : UniFile.fromFile(AppConfig.getDownloadDir()); + return dir != null ? dir : UniFile.fromFile(AppConfig.getArchiveDir()); } public static void putArchiveDownloadLocation(UniFile location) { diff --git a/app/src/main/java/com/hippo/scene/Curtain.java b/app/src/main/java/com/hippo/scene/Curtain.java index 11f85cfe9..66f8bcf09 100644 --- a/app/src/main/java/com/hippo/scene/Curtain.java +++ b/app/src/main/java/com/hippo/scene/Curtain.java @@ -23,7 +23,7 @@ public abstract class Curtain { private int mPreviousSceneId; - void setPreviousScene(@Nullable Scene pScene) { + protected void setPreviousScene(@Nullable Scene pScene) { if (pScene == null) { mPreviousSceneId = -1; } else { @@ -31,17 +31,20 @@ public abstract class Curtain { } } - boolean isPreviousScene(@Nullable Scene scene) { + protected boolean isPreviousScene(@Nullable Scene scene) { return scene != null && scene.getId() == mPreviousSceneId; } /** * @return true if can NOT still run when previous scene changed */ - protected boolean specifyPreviousScene() { + protected boolean needSpecifyPreviousScene() { return true; } + /** + * Scene rebirth + */ protected void onRebirth() { } @@ -72,12 +75,4 @@ public abstract class Curtain { protected void dispatchCloseFinished(@NonNull Scene enter, @NonNull Scene exit) { exit.closeFinished(); } - - protected void hideSceneOnOpen(@NonNull Scene exit) { - exit.setHide(true); - } - - protected void showSceneOnClose(@NonNull Scene enter) { - enter.setHide(false); - } } diff --git a/app/src/main/java/com/hippo/scene/TransitionCurtain.java b/app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java similarity index 56% rename from app/src/main/java/com/hippo/scene/TransitionCurtain.java rename to app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java index 81dd5a21d..eb3763e04 100644 --- a/app/src/main/java/com/hippo/scene/TransitionCurtain.java +++ b/app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java @@ -31,16 +31,15 @@ import com.hippo.animation.ArgbEvaluator; import com.hippo.animation.SimpleAnimatorListener; import com.hippo.util.AnimationUtils; import com.hippo.yorozuya.AssertUtils; -import com.hippo.widget.GlobalLayoutSet; import com.hippo.yorozuya.Say; import com.hippo.yorozuya.ViewUtils; import java.util.HashSet; import java.util.Set; -public class TransitionCurtain extends Curtain { +public class ElementsSharedCurtain extends Curtain { - private static final String TAG = TransitionCurtain.class.getSimpleName(); + private static final String TAG = ElementsSharedCurtain.class.getSimpleName(); private static long ANIMATE_TIME = 300L; @@ -48,16 +47,27 @@ public class TransitionCurtain extends Curtain { private AnimatorSet mAnimatorSet; - public TransitionCurtain(ViewPairSet viewPairSet) { + public ElementsSharedCurtain(ViewPairSet viewPairSet) { mViewPairSet = viewPairSet; } // TODO what if back key press before move animator start - - // Make background from transport to default. - // Invisible other @Override public void open(final @NonNull Scene enter, final @NonNull Scene exit) { + // Check enter content view + View sceneContentView = enter.getSceneView().getChildAt(0); + if (sceneContentView == null) { + Say.w(TAG, "Can't get enter scene content view"); + dispatchOpenFinished(enter, exit); + return; + } + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (!stageLayout.isLayoutRequested()) { + Say.w(TAG, "WTF? stageLayout.isLayoutRequested() == false"); + dispatchOpenFinished(enter, exit); + return; + } final Set animatorCollection = new HashSet<>(); @@ -65,23 +75,17 @@ public class TransitionCurtain extends Curtain { int bgColor = enter.getBackgroundColor(); int startBgColor = bgColor & 0xffffff; enter.setBackgroundColor(startBgColor); - ObjectAnimator colorAnim = ObjectAnimator.ofInt(enter, "backgroundColor", bgColor); + ObjectAnimator colorAnim = ObjectAnimator.ofInt(enter, "backgroundColor", startBgColor, bgColor); colorAnim.setEvaluator(ArgbEvaluator.getInstance()); colorAnim.setDuration(ANIMATE_TIME); animatorCollection.add(colorAnim); - View sceneContentView = enter.getSceneView().getChildAt(0); - if (sceneContentView != null) { - sceneContentView.setAlpha(0f); - ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(sceneContentView, "alpha", 0f, 1f); - alphaAnim.setDuration(ANIMATE_TIME); - animatorCollection.add(alphaAnim); - } else { - Say.w(TAG, "Can't get enter scene content view"); - } + sceneContentView.setAlpha(0f); + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(sceneContentView, "alpha", 0f, 1f); + alphaAnim.setDuration(ANIMATE_TIME); + animatorCollection.add(alphaAnim); - GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); - Set transitionItemSet = new HashSet<>(); + final Set transitionItemSet = new HashSet<>(); // Handle transit part View[] enterViews = mViewPairSet.getToViewSet(enter); @@ -108,131 +112,119 @@ public class TransitionCurtain extends Curtain { item.enterView = enterView; item.exitView = exitView; transitionItemSet.add(item); - - globalLayoutSet.addListenerToObserver(enterView.getViewTreeObserver()); } - if (globalLayoutSet.getSize() == 0) { - // Not transition view, do animation now - new OpenSecondAllLayoutListener(enter, exit, transitionItemSet, animatorCollection).onAllLayout(); + if (transitionItemSet.isEmpty()) { + stageLayout.addOnLayoutListener(new OpenSecondLayoutListener(enter, exit, transitionItemSet, animatorCollection)); } else { - globalLayoutSet.setOnAllLayoutListener(new OpenFirstAllLayoutListener( - enter, exit, transitionItemSet, animatorCollection)); + stageLayout.addOnLayoutListener(new OpenFirstLayoutListener(enter, exit, transitionItemSet, animatorCollection)); } } - private class OpenFirstAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + private class OpenFirstLayoutListener implements StageLayout.OnLayoutListener { - Scene mEnterScene; - Scene mExitScene; - Set mTransitionItemSet; - Set mAnimatorCollection; + private Scene mEnter; + private Scene mExit; + private SceneView mEnterView; + private SceneView mExitView; + private StageLayout mStageLayout; + private Set mTransitionItems; + private Set mAnimatorCollection; - public OpenFirstAllLayoutListener(Scene enterScene, Scene exitScene, - Set transitionItemSet, Set animatorCollection) { - mEnterScene = enterScene; - mExitScene = exitScene; - mTransitionItemSet = transitionItemSet; + public OpenFirstLayoutListener(Scene enter, Scene exit, Set transitionItems, + Set animatorCollection) { + mEnter = enter; + mExit = exit; + mEnterView = enter.getSceneView(); + mExitView = exit.getSceneView(); + mStageLayout = enter.getStageLayout(); + mTransitionItems = transitionItems; mAnimatorCollection = animatorCollection; } - @SuppressWarnings("deprecation") @Override - public void onAllLayout() { - Set transitionItemSet = mTransitionItemSet; + public void onLayout(View view) { + mStageLayout.removeOnLayoutListener(this); - ViewGroup enterSceneView = mEnterScene.getSceneView(); - GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); - - for (TransitionItem item : transitionItemSet) { + int[] startloaction = new int[2]; + int[] endloaction = new int[2]; + for (TransitionItem item : mTransitionItems) { final View enterView = item.enterView; final View exitView = item.exitView; - int[] startloaction = new int[2]; - ViewUtils.getLocationInAncestor(exitView, startloaction, mExitScene.getSceneView()); - int[] endloaction = new int[2]; - ViewUtils.getLocationInAncestor(enterView, endloaction, mEnterScene.getSceneView()); + ViewUtils.getLocationInAncestor(exitView, startloaction, mExitView); + ViewUtils.getLocationInAncestor(enterView, endloaction, mEnterView); int startWidth = exitView.getWidth(); int startHeight = exitView.getHeight(); - item.endWidth = enterView.getWidth(); - item.endHeight = enterView.getHeight(); - item.startWidth = startWidth; - item.startHeight = startHeight; - item.endloaction = endloaction; + // Create bitmap view Bitmap bmp = ViewUtils.getBitmapFromView(enterView); View bmpView = new View(enterView.getContext()); item.bmp = bmp; item.bmpView = bmpView; - - bmpView.setBackgroundDrawable(new BitmapDrawable(bmp)); + bmpView.setBackgroundDrawable(new BitmapDrawable(enterView.getContext().getResources(), bmp)); AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams( startWidth, startHeight, startloaction[0], startloaction[1]); - enterSceneView.addView(bmpView, lp); + mEnterView.addView(bmpView, lp); bmpView.setVisibility(View.INVISIBLE); - globalLayoutSet.addListenerToObserver(bmpView.getViewTreeObserver()); + bmpView.setPivotX(0); + bmpView.setPivotY(0); + + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", 1f, (float) enterView.getWidth() / startWidth); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", 1f, (float) enterView.getHeight() / startHeight); + PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", startloaction[0], endloaction[0]); + PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", startloaction[1], endloaction[1]); + ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(bmpView, scaleXPvh, scaleYPvh, xPvh, yPvh); + anim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + anim.setDuration(ANIMATE_TIME); + + mAnimatorCollection.add(anim); } - globalLayoutSet.setOnAllLayoutListener(new OpenSecondAllLayoutListener( - mEnterScene, mExitScene, transitionItemSet, mAnimatorCollection)); + mStageLayout.addOnLayoutListener(new OpenSecondLayoutListener(mEnter, mExit, mTransitionItems, mAnimatorCollection)); } } - private class OpenSecondAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + private class OpenSecondLayoutListener implements StageLayout.OnLayoutListener { - Scene mEnterScene; - Scene mExitScene; - Set mTransitionItemSet; - Set mAnimatorCollection; + private Scene mEnter; + private Scene mExit; + private Set mTransitionItems; + private Set mAnimatorCollection; - public OpenSecondAllLayoutListener(Scene enterScene, Scene exitScene, - Set transitionItemSet, Set animatorCollection) { - mEnterScene = enterScene; - mExitScene = exitScene; - mTransitionItemSet = transitionItemSet; + public OpenSecondLayoutListener(Scene enter, Scene exit, Set transitionItems, + Set animatorCollection) { + mEnter = enter; + mExit = exit; + mTransitionItems = transitionItems; mAnimatorCollection = animatorCollection; } @Override - public void onAllLayout() { - Set transitionItemSet = mTransitionItemSet; - Set animatorCollection = mAnimatorCollection; + public void onLayout(View view) { + mEnter.getStageLayout().removeOnLayoutListener(this); - for (TransitionItem item : transitionItemSet) { + for (TransitionItem item : mTransitionItems) { View exitView = item.exitView; View bmpView = item.bmpView; exitView.setVisibility(View.INVISIBLE); bmpView.setVisibility(View.VISIBLE); - - bmpView.setPivotX(0); - bmpView.setPivotY(0); - - PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", (float) item.endWidth / item.startWidth); - PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", (float) item.endHeight/ item.startHeight); - PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", item.endloaction[0]); - PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", item.endloaction[1]); - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(bmpView, scaleXPvh, scaleYPvh, xPvh, yPvh); - anim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); - anim.setDuration(ANIMATE_TIME); - - animatorCollection.add(anim); } mAnimatorSet = new AnimatorSet(); - mAnimatorSet.playTogether(animatorCollection); + mAnimatorSet.playTogether(mAnimatorCollection); mAnimatorSet.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { - dispatchOpenFinished(mEnterScene, mExitScene); - hideSceneOnOpen(mExitScene); - for (TransitionItem item : mTransitionItemSet) { + dispatchOpenFinished(mEnter, mExit); + ViewGroup enterSceneView = mEnter.getSceneView(); + for (TransitionItem item : mTransitionItems) { item.enterView.setVisibility(View.VISIBLE); item.exitView.setVisibility(View.VISIBLE); - ViewGroup enterSceneView = mEnterScene.getSceneView(); enterSceneView.removeView(item.bmpView); item.bmp.recycle(); @@ -244,31 +236,30 @@ public class TransitionCurtain extends Curtain { } } - @Override public void close(final @NonNull Scene enter, final @NonNull Scene exit) { - showSceneOnClose(enter); + // Check enter content view + View sceneContentView = exit.getSceneView().getChildAt(0); + if (sceneContentView == null) { + Say.w(TAG, "Can't get exit scene content view"); + dispatchOpenFinished(enter, exit); + return; + } final Set animatorCollection = new HashSet<>(); // Handle background int bgColor = exit.getBackgroundColor(); int endBgColor = bgColor & 0xffffff; - ObjectAnimator colorAnim = ObjectAnimator.ofInt(exit, "backgroundColor", endBgColor); + ObjectAnimator colorAnim = ObjectAnimator.ofInt(exit, "backgroundColor", bgColor, endBgColor); colorAnim.setEvaluator(ArgbEvaluator.getInstance()); colorAnim.setDuration(ANIMATE_TIME); animatorCollection.add(colorAnim); - View sceneContentView = exit.getSceneView().getChildAt(0); - if (sceneContentView != null) { - ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(sceneContentView, "alpha", 0f); - alphaAnim.setDuration(ANIMATE_TIME); - animatorCollection.add(alphaAnim); - } else { - Say.w(TAG, "Can't get enter scene content view"); - } + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(sceneContentView, "alpha", 1f, 0f); + alphaAnim.setDuration(ANIMATE_TIME); + animatorCollection.add(alphaAnim); - GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); Set transitionItemSet = new HashSet<>(); // Handle transit part @@ -296,56 +287,59 @@ public class TransitionCurtain extends Curtain { item.enterView = enterView; item.exitView = exitView; transitionItemSet.add(item); - - globalLayoutSet.addListenerToObserver(enterView.getViewTreeObserver()); } - if (globalLayoutSet.getSize() == 0) { - new CloseSecondAllLayoutListener(enter, exit, transitionItemSet, animatorCollection).onAllLayout(); + final StageLayout stageLayout = enter.getStageLayout(); + if (stageLayout.isLayoutRequested()) { + if (transitionItemSet.isEmpty()) { + stageLayout.addOnLayoutListener(new CloseSecondLayoutListener(enter, exit, transitionItemSet, animatorCollection)); + } else { + stageLayout.addOnLayoutListener(new CloseFirstLayoutListener(enter, exit, transitionItemSet, animatorCollection)); + } } else { - globalLayoutSet.setOnAllLayoutListener(new CloseFirstAllLayoutListener( - enter, exit, transitionItemSet, animatorCollection)); + if (transitionItemSet.isEmpty()) { + new CloseSecondLayoutListener(enter, exit, transitionItemSet, animatorCollection).onLayout(stageLayout); + } else { + new CloseFirstLayoutListener(enter, exit, transitionItemSet, animatorCollection).onLayout(stageLayout); + } } } - private class CloseFirstAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + private class CloseFirstLayoutListener implements StageLayout.OnLayoutListener { - Scene mEnterScene; - Scene mExitScene; - Set mTransitionItemSet; - Set mAnimatorCollection; + private Scene mEnter; + private Scene mExit; + private SceneView mEnterView; + private SceneView mExitView; + private StageLayout mStageLayout; + private Set mTransitionItems; + private Set mAnimatorCollection; - public CloseFirstAllLayoutListener(Scene enterScene, Scene exitScene, - Set transitionItemSet, Set animatorCollection) { - mEnterScene = enterScene; - mExitScene = exitScene; - mTransitionItemSet = transitionItemSet; + public CloseFirstLayoutListener(Scene enter, Scene exit, Set transitionItems, + Set animatorCollection) { + mEnter = enter; + mExit = exit; + mEnterView = enter.getSceneView(); + mExitView = exit.getSceneView(); + mStageLayout = enter.getStageLayout(); + mTransitionItems = transitionItems; mAnimatorCollection = animatorCollection; } - @SuppressWarnings("deprecation") @Override - public void onAllLayout() { - Set transitionItemSet = mTransitionItemSet; + public void onLayout(View view) { + mStageLayout.removeOnLayoutListener(this); - ViewGroup exitSceneView = mExitScene.getSceneView(); - GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); - - for (TransitionItem item : transitionItemSet) { + int[] startloaction = new int[2]; + int[] endloaction = new int[2]; + for (TransitionItem item : mTransitionItems) { final View enterView = item.enterView; final View exitView = item.exitView; - int[] startloaction = new int[2]; - ViewUtils.getLocationInAncestor(exitView, startloaction, mExitScene.getSceneView()); - int[] endloaction = new int[2]; - ViewUtils.getLocationInAncestor(enterView, endloaction, mEnterScene.getSceneView()); + ViewUtils.getLocationInAncestor(exitView, startloaction, mExitView); + ViewUtils.getLocationInAncestor(enterView, endloaction, mEnterView); int startWidth = exitView.getWidth(); int startHeight = exitView.getHeight(); - item.endWidth = enterView.getWidth(); - item.endHeight = enterView.getHeight(); - item.startWidth = startWidth; - item.startHeight = startHeight; - item.endloaction = endloaction; Bitmap bmp = ViewUtils.getBitmapFromView(enterView); View bmpView = new View(exitView.getContext()); @@ -355,70 +349,66 @@ public class TransitionCurtain extends Curtain { bmpView.setBackgroundDrawable(new BitmapDrawable(bmp)); AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams( startWidth, startHeight, startloaction[0], startloaction[1]); - exitSceneView.addView(bmpView, lp); + mExitView.addView(bmpView, lp); bmpView.setVisibility(View.INVISIBLE); - globalLayoutSet.addListenerToObserver(bmpView.getViewTreeObserver()); + bmpView.setPivotX(0); + bmpView.setPivotY(0); + + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", 1f, (float) enterView.getWidth() / startWidth); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", 1f, (float) enterView.getHeight() / startHeight); + PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", startloaction[0], endloaction[0]); + PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", startloaction[1], endloaction[1]); + ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(bmpView, scaleXPvh, scaleYPvh, xPvh, yPvh); + anim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + anim.setDuration(ANIMATE_TIME); + + mAnimatorCollection.add(anim); } - globalLayoutSet.setOnAllLayoutListener(new CloseSecondAllLayoutListener( - mEnterScene, mExitScene, transitionItemSet, mAnimatorCollection)); + mStageLayout.addOnLayoutListener(new CloseSecondLayoutListener(mEnter, mExit, mTransitionItems, mAnimatorCollection)); } } - private class CloseSecondAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + private class CloseSecondLayoutListener implements StageLayout.OnLayoutListener { - Scene mEnterScene; - Scene mExitScene; - Set mTransitionItemSet; - Set mAnimatorCollection; + private Scene mEnter; + private Scene mExit; + private Set mTransitionItems; + private Set mAnimatorCollection; - public CloseSecondAllLayoutListener(Scene enterScene, Scene exitScene, - Set transitionItemSet, Set animatorCollection) { - mEnterScene = enterScene; - mExitScene = exitScene; - mTransitionItemSet = transitionItemSet; + public CloseSecondLayoutListener(Scene enter, Scene exit, Set transitionItems, + Set animatorCollection) { + mEnter = enter; + mExit = exit; + mTransitionItems = transitionItems; mAnimatorCollection = animatorCollection; } @Override - public void onAllLayout() { - Set transitionItemSet = mTransitionItemSet; - Set animatorCollection = mAnimatorCollection; + public void onLayout(View view) { + mEnter.getStageLayout().removeOnLayoutListener(this); - for (TransitionItem item : transitionItemSet) { + for (TransitionItem item : mTransitionItems) { View exitView = item.exitView; View bmpView = item.bmpView; exitView.setVisibility(View.INVISIBLE); bmpView.setVisibility(View.VISIBLE); - - bmpView.setPivotX(0); - bmpView.setPivotY(0); - - PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", (float) item.endWidth / item.startWidth); - PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", (float) item.endHeight/ item.startHeight); - PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", item.endloaction[0]); - PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", item.endloaction[1]); - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(bmpView, scaleXPvh, scaleYPvh, xPvh, yPvh); - anim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); - anim.setDuration(ANIMATE_TIME); - - animatorCollection.add(anim); } mAnimatorSet = new AnimatorSet(); - mAnimatorSet.playTogether(animatorCollection); + mAnimatorSet.playTogether(mAnimatorCollection); mAnimatorSet.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { - dispatchCloseFinished(mEnterScene, mExitScene); - for (TransitionItem item : mTransitionItemSet) { + dispatchCloseFinished(mEnter, mExit); + ViewGroup exitSceneView = mExit.getSceneView(); + for (TransitionItem item : mTransitionItems) { item.enterView.setVisibility(View.VISIBLE); item.exitView.setVisibility(View.VISIBLE); - ViewGroup exitSceneView = mExitScene.getSceneView(); exitSceneView.removeView(item.bmpView); item.bmp.recycle(); @@ -447,15 +437,10 @@ public class TransitionCurtain extends Curtain { View exitView; Bitmap bmp; View bmpView; - int[] endloaction; - int startWidth; - int startHeight; - int endWidth; - int endHeight; } /** - * the interface help {@link TransitionCurtain} to get the views to do transfer + * the interface help {@link ElementsSharedCurtain} to get the views to do transfer */ public interface ViewPairSet { View[] getFromViewSet(@NonNull Scene fromScene); diff --git a/app/src/main/java/com/hippo/scene/OffsetCurtain.java b/app/src/main/java/com/hippo/scene/OffsetCurtain.java new file mode 100644 index 000000000..d07c07ddf --- /dev/null +++ b/app/src/main/java/com/hippo/scene/OffsetCurtain.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.support.annotation.NonNull; +import android.view.View; + +import com.hippo.animation.SimpleAnimatorListener; +import com.hippo.util.AnimationUtils; +import com.hippo.yorozuya.Say; + +import java.util.HashSet; +import java.util.Set; + +public class OffsetCurtain extends Curtain { + + private static final String TAG = OffsetCurtain.class.getSimpleName(); + + private static long ANIMATE_TIME = 300L; + + public static final int DIRECTION_LEFT = 0; + public static final int DIRECTION_TOP = 1; + public static final int DIRECTION_RIGHT = 2; + public static final int DIRECTION_BOTTOM = 3; + + private int mDirection; + private float mOffsetPercent; + + private AnimatorSet mAnimatorSet; + + public OffsetCurtain(int direction) { + this(direction, 0.25f); + } + + public OffsetCurtain(int direction, float offsetPercent) { + mDirection = direction; + mOffsetPercent = offsetPercent; + } + + @Override + protected boolean needSpecifyPreviousScene() { + return false; + } + + @Override + public void open(@NonNull final Scene enter, @NonNull final Scene exit) { + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (!stageLayout.isLayoutRequested()) { + Say.w(TAG, "WTF? stageLayout.isLayoutRequested() == false"); + dispatchOpenFinished(enter, exit); + return; + } + + final View enterSceneView = enter.getSceneView(); + enterSceneView.setVisibility(View.INVISIBLE); + + stageLayout.addOnLayoutListener(new StageLayout.OnLayoutListener() { + @Override + public void onLayout(View view) { + stageLayout.removeOnLayoutListener(this); + + final Set animatorCollection = new HashSet<>(); + + int width = enterSceneView.getWidth(); + int height = enterSceneView.getHeight(); + float translationX = 0f; + float translationY = 0f; + switch (mDirection) { + case DIRECTION_LEFT: + translationX = -width * mOffsetPercent; + break; + case DIRECTION_TOP: + translationY = -height * mOffsetPercent; + break; + case DIRECTION_RIGHT: + translationX = width * mOffsetPercent; + break; + default: + case DIRECTION_BOTTOM: + translationY = height * mOffsetPercent; + break; + } + PropertyValuesHolder pvh; + if (translationX != 0f) { + pvh = PropertyValuesHolder.ofFloat("translationX", translationX, 0f); + } else { + pvh = PropertyValuesHolder.ofFloat("translationY", translationY, 0f); + } + Animator offsetAnimator = ObjectAnimator.ofPropertyValuesHolder(enterSceneView, pvh); + offsetAnimator.setDuration(ANIMATE_TIME); + offsetAnimator.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + animatorCollection.add(offsetAnimator); + + View enterView = enter.getSceneView(); + enterView.setAlpha(0f); + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(enterView, "alpha", 0f, 1f); + alphaAnim.setDuration(ANIMATE_TIME); + alphaAnim.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); + animatorCollection.add(alphaAnim); + + mAnimatorSet = new AnimatorSet(); + mAnimatorSet.playTogether(animatorCollection); + mAnimatorSet.addListener(new SimpleAnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + enterSceneView.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + dispatchOpenFinished(enter, exit); + mAnimatorSet = null; + } + }); + mAnimatorSet.start(); + } + }); + } + + @Override + public void close(@NonNull final Scene enter, @NonNull final Scene exit) { + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (stageLayout.isLayoutRequested()) { + stageLayout.addOnLayoutListener(new StageLayout.OnLayoutListener() { + @Override + public void onLayout(View view) { + stageLayout.removeOnLayoutListener(this); + onClose(enter, exit); + } + }); + } else { + onClose(enter, exit); + } + } + + private void onClose(final Scene enter, final Scene exit) { + final Set animatorCollection = new HashSet<>(); + + final View exitSceneView = exit.getSceneView(); + int width = exitSceneView.getWidth(); + int height = exitSceneView.getHeight(); + float translationX = 0f; + float translationY = 0f; + switch (mDirection) { + case DIRECTION_LEFT: + translationX = -width * mOffsetPercent; + break; + case DIRECTION_TOP: + translationY = -height * mOffsetPercent; + break; + case DIRECTION_RIGHT: + translationX = width * mOffsetPercent; + break; + default: + case DIRECTION_BOTTOM: + translationY = height * mOffsetPercent; + break; + } + PropertyValuesHolder pvh; + if (translationX != 0f) { + pvh = PropertyValuesHolder.ofFloat("translationX", 0f, translationX); + } else { + pvh = PropertyValuesHolder.ofFloat("translationY", 0f, translationY); + } + Animator offsetAnimator = ObjectAnimator.ofPropertyValuesHolder(exitSceneView, pvh); + offsetAnimator.setDuration(ANIMATE_TIME); + offsetAnimator.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); + animatorCollection.add(offsetAnimator); + + View exitView = exit.getSceneView(); + exitView.setAlpha(1f); + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(exitView, "alpha", 1f, 0f); + alphaAnim.setDuration(ANIMATE_TIME); + alphaAnim.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); + animatorCollection.add(alphaAnim); + + mAnimatorSet = new AnimatorSet(); + mAnimatorSet.playTogether(animatorCollection); + mAnimatorSet.addListener(new SimpleAnimatorListener() { + @Override + public void onAnimationEnd(Animator animation) { + dispatchCloseFinished(enter, exit); + mAnimatorSet = null; + } + }); + mAnimatorSet.start(); + } + + @Override + public void endAnimation() { + if (mAnimatorSet != null) { + mAnimatorSet.end(); + } + } + + @Override + public boolean isInAnimation() { + return mAnimatorSet != null; + } +} diff --git a/app/src/main/java/com/hippo/scene/RippleCurtain.java b/app/src/main/java/com/hippo/scene/RippleCurtain.java index b07cb0ec2..d48c23333 100644 --- a/app/src/main/java/com/hippo/scene/RippleCurtain.java +++ b/app/src/main/java/com/hippo/scene/RippleCurtain.java @@ -6,12 +6,10 @@ import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.support.annotation.NonNull; import android.view.View; -import android.view.ViewTreeObserver; import com.hippo.animation.DurationInterpolator; import com.hippo.animation.SimpleAnimatorListener; import com.hippo.yorozuya.Say; -import com.hippo.yorozuya.ViewUtils; import java.util.HashSet; import java.util.Set; @@ -33,6 +31,11 @@ public class RippleCurtain extends Curtain { mStartY = startY; } + @Override + protected boolean needSpecifyPreviousScene() { + return false; + } + @Override protected void onRebirth() { mStartX = 0; @@ -41,16 +44,24 @@ public class RippleCurtain extends Curtain { @Override public void open(@NonNull final Scene enter, @NonNull final Scene exit) { + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (!stageLayout.isLayoutRequested()) { + Say.w(TAG, "WTF? stageLayout.isLayoutRequested() == false"); + dispatchOpenFinished(enter, exit); + return; + } + final Set animatorCollection = new HashSet<>(); final SceneView enterView = enter.getSceneView(); enterView.setStartPoint(mStartX, mStartY); enterView.setVisibility(View.INVISIBLE); - enterView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + stageLayout.addOnLayoutListener(new StageLayout.OnLayoutListener() { @Override - public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(enterView.getViewTreeObserver(), this); + public void onLayout(View view) { + stageLayout.removeOnLayoutListener(this); final View sceneContentView = enter.getSceneView().getChildAt(0); if (sceneContentView != null) { @@ -85,7 +96,6 @@ public class RippleCurtain extends Curtain { @Override public void onAnimationEnd(Animator animation) { dispatchOpenFinished(enter, exit); - hideSceneOnOpen(exit); mAnimatorSet = null; } }); @@ -96,8 +106,22 @@ public class RippleCurtain extends Curtain { @Override public void close(@NonNull final Scene enter, @NonNull final Scene exit) { - showSceneOnClose(enter); + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (stageLayout.isLayoutRequested()) { + stageLayout.addOnLayoutListener(new StageLayout.OnLayoutListener() { + @Override + public void onLayout(View view) { + stageLayout.removeOnLayoutListener(this); + onClose(enter, exit); + } + }); + } else { + onClose(enter, exit); + } + } + private void onClose(final Scene enter, final Scene exit) { final Set animatorCollection = new HashSet<>(); final SceneView exitView = exit.getSceneView(); diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index e757e70aa..bebd7f3f6 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -26,12 +26,10 @@ import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; -import android.view.ViewTreeObserver; import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; import com.hippo.yorozuya.AssertUtils; -import com.hippo.yorozuya.ViewUtils; /** * {@link com.hippo.scene.Scene} is a {@code Activity} of {@link android.app.Activity}. @@ -68,7 +66,7 @@ public abstract class Scene { private int mId; - private boolean mHide; + private boolean mHide = false; public void setSceneManager(SceneManager sceneManager) { mSceneManager = sceneManager; @@ -123,16 +121,20 @@ public abstract class Scene { } public void startScene(@NonNull Class sceneClass) { - mSceneManager.startScene(sceneClass, null, null); + startScene(sceneClass, null, null); } public void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer) { - mSceneManager.startScene(sceneClass, announcer, null); + startScene(sceneClass, announcer, null); + } + + public Curtain getDefaultCurtain() { + return new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM); } public void startScene(@NonNull Class sceneClass, @Nullable Announcer announcer, @Nullable Curtain curtain) { - mSceneManager.startScene(sceneClass, announcer, curtain); + mSceneManager.startScene(sceneClass, announcer, curtain == null ? getDefaultCurtain() : curtain); } int getState() { @@ -148,20 +150,33 @@ public abstract class Scene { } public final void finish() { - mSceneManager.finishScene(this); + mSceneManager.finishScene(this, false); + } + + /** + * Tell {@link SceneManager} how to {@link View#setVisibility(int)} when it is not the first scene. + * If it covers previous scene completely, {@link SceneManager} will setVisibility(View.INVISIBLE), + * otherwise setVisibility(View.VISIBLE) + * + * @return {@code true} if it covers previous scene completely + */ + protected boolean coverCompletely() { + return true; } void setHide(boolean hide) { checkSceneView(); - mHide = hide; - if (hide) { - mSceneView.setVisibility(View.GONE); - } else { - mSceneView.setVisibility(View.VISIBLE); + if (mHide != hide) { + mHide = hide; + if (hide) { + mSceneView.setVisibility(View.INVISIBLE); + } else { + mSceneView.setVisibility(View.VISIBLE); + } } } - boolean getHide() { + boolean isHide() { return mHide; } @@ -197,13 +212,8 @@ public abstract class Scene { // Hide it if it is hidden if (mHide) { mSceneView.setVisibility(View.INVISIBLE); - mSceneView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(mSceneView.getViewTreeObserver(), this); - mSceneView.setVisibility(View.GONE); - } - }); + } else { + mSceneView.setVisibility(View.VISIBLE); } } @@ -397,6 +407,10 @@ public abstract class Scene { } } + public StageLayout getStageLayout() { + return getStageActivity().getStageLayout(); + } + // Add scene view to stage layout void attachToStage() { if (mSceneView != null && !isInStage()) { diff --git a/app/src/main/java/com/hippo/scene/SceneManager.java b/app/src/main/java/com/hippo/scene/SceneManager.java index 81eb2c95a..c914b9fb0 100644 --- a/app/src/main/java/com/hippo/scene/SceneManager.java +++ b/app/src/main/java/com/hippo/scene/SceneManager.java @@ -116,10 +116,14 @@ public class SceneManager { } } - private void checkPrepareToDie(Scene scene) { + /// Ture is finishScene is called + private boolean checkPrepareToDie(Scene scene) { if (mPrepareToDieSceneSet.contains(scene)) { mPrepareToDieSceneSet.remove(scene); - finishScene(scene); + finishScene(scene, true); + return true; + } else { + return false; } } @@ -175,6 +179,20 @@ public class SceneManager { startScene(dialog, curtain); } + private void updateSceneVisibility() { + int pointer = mSceneStack.size() - 1; + for (; pointer >= 0; pointer--) { + Scene scene = mSceneStack.get(pointer); + scene.setHide(false); + if (scene.coverCompletely()) { + break; + } + } + for (pointer--; pointer >= 0; pointer--) { + mSceneStack.get(pointer).setHide(true); + } + } + private void startScene(Scene scene, Curtain curtain) { Scene previousState = getTopScene(); mSceneStack.push(scene); @@ -199,13 +217,18 @@ public class SceneManager { scene.setFitPaddingBottom(fitPaddingBottom); } - 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); - checkPrepareToDie(scene); + scene.setState(Scene.SCENE_STATE_RUN); + if (!checkPrepareToDie(scene)) { + // No finish called. Go on + if (curtain != null && previousState != null) { + scene.setState(Scene.SCENE_STATE_OPEN); + curtain.open(scene, previousState); + } else { + // No curtain, set visiblity for previousState here + if (previousState != null) { + updateSceneVisibility(); + } + } } } @@ -228,7 +251,7 @@ public class SceneManager { } } - void finishScene(@NonNull Scene scene) { + void finishScene(@NonNull Scene scene, boolean noAnimation) { checkLoop(); int index = getSceneIndex(scene); @@ -248,7 +271,7 @@ public class SceneManager { // TODO If the cene is under a dialog, the previous may not show if (index != mSceneStack.size() - 1 || index == 0) { - // It is the last scene, just finish the activity + // It is not the first or it is the last scene mSceneStack.remove(index); scene.destroy(true); scene.setState(Scene.SCENE_STATE_DESTROY); @@ -256,7 +279,11 @@ public class SceneManager { scene.setState(Scene.SCENE_STATE_DIE); if (index == 0) { + // It is the last scene, just finish the activity getStageActivity().finish(); + } else { + // Update the scene under target scene visibility + updateSceneVisibility(); } } else { mSceneStack.remove(index); @@ -267,9 +294,12 @@ public class SceneManager { scene.destroy(true); + // Update scene visibility + updateSceneVisibility(); + Curtain curtain = scene.getCurtain(); - if (curtain != null && - (!curtain.specifyPreviousScene() || curtain.isPreviousScene(previousScene))) { + if (!noAnimation && curtain != null && + (!curtain.needSpecifyPreviousScene() || curtain.isPreviousScene(previousScene))) { scene.setState(Scene.SCENE_STATE_CLOSE); curtain.close(previousScene, scene); // add the scene to legacy set @@ -279,6 +309,8 @@ public class SceneManager { scene.setState(Scene.SCENE_STATE_DESTROY); scene.die(false); scene.setState(Scene.SCENE_STATE_DIE); + + previousScene.setHide(false); } } } else { @@ -296,6 +328,7 @@ public class SceneManager { scene.open(); scene.setState(Scene.SCENE_STATE_RUN); checkPrepareToDie(scene); + updateSceneVisibility(); } void closeScene(Scene scene) { diff --git a/app/src/main/java/com/hippo/scene/SimpleCurtain.java b/app/src/main/java/com/hippo/scene/SimpleCurtain.java deleted file mode 100644 index 3b5e4dbc0..000000000 --- a/app/src/main/java/com/hippo/scene/SimpleCurtain.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.scene; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; -import android.support.annotation.NonNull; -import android.view.View; -import android.view.ViewTreeObserver; - -import com.hippo.animation.SimpleAnimatorListener; -import com.hippo.util.AnimationUtils; -import com.hippo.yorozuya.ViewUtils; - -public class SimpleCurtain extends Curtain { - - private static long ANIMATE_TIME = 300L; - - public static final int DIRECTION_LEFT = 0; - public static final int DIRECTION_TOP = 1; - public static final int DIRECTION_RIGHT = 2; - public static final int DIRECTION_BOTTOM = 3; - - private int mDirection; - - private Animator mAnimator; - - public SimpleCurtain(int direction) { - mDirection = direction; - } - - @Override - public void open(@NonNull final Scene enter, @NonNull final Scene exit) { - final View enterSceneView = enter.getSceneView(); - enterSceneView.setVisibility(View.INVISIBLE); - - enterSceneView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(enterSceneView.getViewTreeObserver(), this); - - int width = enterSceneView.getWidth(); - int height = enterSceneView.getHeight(); - float translationX = 0f; - float translationY = 0f; - switch (mDirection) { - case DIRECTION_LEFT: - translationX = -width; - break; - case DIRECTION_TOP: - translationY = -height; - break; - case DIRECTION_RIGHT: - translationX = width; - break; - default: - case DIRECTION_BOTTOM: - translationY = height; - break; - } - PropertyValuesHolder pvh; - if (translationX != 0f) { - pvh = PropertyValuesHolder.ofFloat("translationX", translationX, 0f); - } else { - pvh = PropertyValuesHolder.ofFloat("translationY", translationY, 0f); - } - Animator animator = ObjectAnimator.ofPropertyValuesHolder(enterSceneView, pvh); - animator.setDuration(ANIMATE_TIME); - animator.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); - animator.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - enterSceneView.setVisibility(View.VISIBLE); - } - - @Override - public void onAnimationEnd(Animator animation) { - dispatchOpenFinished(enter, exit); - hideSceneOnOpen(exit); - mAnimator = null; - } - }); - animator.start(); - mAnimator = animator; - } - }); - } - - @Override - public void close(@NonNull final Scene enter, @NonNull final Scene exit) { - showSceneOnClose(enter); - - final View exitSceneView = exit.getSceneView(); - int width = exitSceneView.getWidth(); - int height = exitSceneView.getHeight(); - float translationX = 0f; - float translationY = 0f; - switch (mDirection) { - case DIRECTION_LEFT: - translationX = -width; - break; - case DIRECTION_TOP: - translationY = -height; - break; - case DIRECTION_RIGHT: - translationX = width; - break; - default: - case DIRECTION_BOTTOM: - translationY = height; - break; - } - PropertyValuesHolder pvh; - if (translationX != 0f) { - pvh = PropertyValuesHolder.ofFloat("translationX", 0f, translationX); - } else { - pvh = PropertyValuesHolder.ofFloat("translationY", 0f, translationY); - } - Animator animator = ObjectAnimator.ofPropertyValuesHolder(exitSceneView, pvh); - animator.setDuration(ANIMATE_TIME); - animator.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); - animator.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationEnd(Animator animation) { - dispatchCloseFinished(enter, exit); - mAnimator = null; - } - }); - animator.start(); - mAnimator = animator; - } - - @Override - public void endAnimation() { - if (mAnimator != null) { - mAnimator.end(); - } - } - - @Override - public boolean isInAnimation() { - return mAnimator != null; - } -} diff --git a/app/src/main/java/com/hippo/scene/SimpleDialog.java b/app/src/main/java/com/hippo/scene/SimpleDialog.java index efe236d87..9d1f6b95e 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialog.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialog.java @@ -110,6 +110,11 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener, } } + @Override + protected boolean coverCompletely() { + return false; + } + private void bindDialog() { ListView listView = mListView; @@ -192,6 +197,10 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener, mLayout.setFitPaddingBottom(b); } + public ViewGroup getLayout() { + return mLayout; + } + public CardView getCushion() { return mCushion; } diff --git a/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java b/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java index c70d26502..d5e11f008 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialogCurtain.java @@ -22,20 +22,22 @@ import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.support.annotation.NonNull; import android.view.View; -import android.view.ViewTreeObserver; import com.hippo.animation.ArgbEvaluator; import com.hippo.animation.SimpleAnimatorListener; import com.hippo.util.AnimationUtils; import com.hippo.yorozuya.AssertUtils; -import com.hippo.yorozuya.ViewUtils; +import com.hippo.yorozuya.Say; import java.util.HashSet; import java.util.Set; public class SimpleDialogCurtain extends Curtain { + private static final String TAG = SimpleDialogCurtain.class.getSimpleName(); + private static long ANIMATE_TIME = 300L; + private static float SCALE_PERCENT = 0.75f; private int mStartX; private int mStartY; @@ -57,14 +59,22 @@ public class SimpleDialogCurtain extends Curtain { } @Override - protected void onRebirth() { - mStartX = 0; - mStartY = 0; + protected boolean needSpecifyPreviousScene() { + return false; } @Override public void open(@NonNull final Scene enter, @NonNull final Scene exit) { AssertUtils.assertInstanceof("SimpleDialogCurtain should only use for SimpleDialog.", enter, SimpleDialog.class); + + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (!stageLayout.isLayoutRequested()) { + Say.w(TAG, "WTF? stageLayout.isLayoutRequested() == false"); + dispatchOpenFinished(enter, exit); + return; + } + final SimpleDialog enterDialog = (SimpleDialog) enter; final Set animatorCollection = new HashSet<>(); @@ -87,13 +97,10 @@ public class SimpleDialogCurtain extends Curtain { cushion.setVisibility(View.INVISIBLE); frame.setVisibility(View.INVISIBLE); - // TODO addOnGlobalLayoutListener is not reliable - // TODO use isLayoutRequested - // TODO if isLayoutRequested return false, try to use StageView Size - frame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + stageLayout.addOnLayoutListener(new StageLayout.OnLayoutListener() { @Override - public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(frame.getViewTreeObserver(), this); + public void onLayout(View view) { + stageLayout.removeOnLayoutListener(this); float floatStartX; float floatStartY; @@ -141,6 +148,7 @@ public class SimpleDialogCurtain extends Curtain { cushion.setVisibility(View.VISIBLE); frame.setVisibility(View.VISIBLE); } + @Override public void onAnimationEnd(Animator animation) { dispatchOpenFinished(enter, exit); @@ -168,44 +176,48 @@ public class SimpleDialogCurtain extends Curtain { animatorCollection.add(colorAnim); colorAnim.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); + final View layout = exitDialog.getLayout(); final View cushion = exitDialog.getCushion(); final View frame = exitDialog.getFrame(); AssertUtils.assertNotNull("Cushion view must not be null.", cushion); AssertUtils.assertNotNull("Frame view must not be null.", frame); - float floatEndX; - float floatEndY; - int intEndX; - int intEndY; - if (mStartX == 0 && mStartY == 0) { - int[] center = new int[2]; - exitDialog.getCenterLocation(center); - floatEndX = center[0]; - floatEndY = center[1]; - intEndX = center[0]; - intEndY = center[1]; + // Check stage layout isLayoutRequested + final StageLayout stageLayout = enter.getStageLayout(); + if (stageLayout.isLayoutRequested()) { + stageLayout.addOnLayoutListener(new StageLayout.OnLayoutListener() { + @Override + public void onLayout(View view) { + onClose(enter, exitDialog, layout, cushion, frame, animatorCollection); + } + }); } else { - floatEndX = mStartX; - floatEndY = mStartY; - intEndX = mStartX; - intEndY = mStartY; + onClose(enter, exitDialog, layout, cushion, frame, animatorCollection); } + } - cushion.setPivotX(0f); - cushion.setPivotY(0f); - PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", 0f); - PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", 0f); - PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", floatEndX); - PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", floatEndY); - ObjectAnimator animCushion = ObjectAnimator.ofPropertyValuesHolder(cushion, scaleXPvh, scaleYPvh, xPvh, yPvh); + private void onClose(final Scene enter, final SimpleDialog exitDialog, View layout, View cushion, View frame, Set animatorCollection) { + + layout.setAlpha(1f); + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(layout, "alpha", 1f, 0f); + alphaAnim.setDuration(ANIMATE_TIME); + animatorCollection.add(alphaAnim); + + cushion.setPivotX(cushion.getWidth() / 2); + cushion.setPivotY(cushion.getHeight() / 2); + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", 1f, SCALE_PERCENT); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", 1f, SCALE_PERCENT); + ObjectAnimator animCushion = ObjectAnimator.ofPropertyValuesHolder(cushion, scaleXPvh, scaleYPvh); animCushion.setDuration(ANIMATE_TIME); animCushion.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); animatorCollection.add(animCushion); - PropertyValuesHolder leftPvh = PropertyValuesHolder.ofInt("drawLeft", intEndX); - PropertyValuesHolder topPvh = PropertyValuesHolder.ofInt("drawTop", intEndY); - PropertyValuesHolder rightPvh = PropertyValuesHolder.ofInt("drawRight", intEndX); - PropertyValuesHolder bottomPvh = PropertyValuesHolder.ofInt("drawBottom", intEndY); + int dx = (int) (frame.getWidth() * (1 - SCALE_PERCENT) / 2); + int dy = (int) (frame.getHeight() * (1 - SCALE_PERCENT) / 2); + PropertyValuesHolder leftPvh = PropertyValuesHolder.ofInt("drawLeft", frame.getLeft() + dx); + PropertyValuesHolder topPvh = PropertyValuesHolder.ofInt("drawTop", frame.getTop() + dy); + PropertyValuesHolder rightPvh = PropertyValuesHolder.ofInt("drawRight", frame.getRight() - dx); + PropertyValuesHolder bottomPvh = PropertyValuesHolder.ofInt("drawBottom", frame.getBottom() - dy); ObjectAnimator animFrame = ObjectAnimator.ofPropertyValuesHolder(frame, leftPvh, topPvh, rightPvh, bottomPvh); animFrame.setDuration(ANIMATE_TIME); animFrame.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); @@ -216,7 +228,7 @@ public class SimpleDialogCurtain extends Curtain { mAnimatorSet.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { - dispatchCloseFinished(enter, exit); + dispatchCloseFinished(enter, exitDialog); mAnimatorSet = null; } }); diff --git a/app/src/main/java/com/hippo/scene/StageLayout.java b/app/src/main/java/com/hippo/scene/StageLayout.java index f77cb4258..d8b2e50d4 100644 --- a/app/src/main/java/com/hippo/scene/StageLayout.java +++ b/app/src/main/java/com/hippo/scene/StageLayout.java @@ -21,10 +21,17 @@ import android.os.Parcelable; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.util.SparseArray; +import android.view.View; import android.widget.FrameLayout; +import java.util.ArrayList; +import java.util.List; + public class StageLayout extends FrameLayout { + private List mOnLayoutListeners = new ArrayList<>(3); + private List mOnLayoutListenersCopy = new ArrayList<>(3); + public StageLayout(Context context) { super(context); } @@ -46,4 +53,31 @@ public class StageLayout extends FrameLayout { protected void dispatchRestoreInstanceState(@NonNull SparseArray container) { // Do nothing } + + public void addOnLayoutListener(OnLayoutListener layoutListener) { + mOnLayoutListeners.add(layoutListener); + } + + public void removeOnLayoutListener(OnLayoutListener layoutListener) { + mOnLayoutListeners.remove(layoutListener); + } + + @Override + protected void onLayout(boolean changed, int l, int t, + int r, int b) { + super.onLayout(changed, l, t, r, b); + + mOnLayoutListenersCopy.clear(); + for (int i = 0, n = mOnLayoutListeners.size(); i < n; i++) { + mOnLayoutListenersCopy.add(mOnLayoutListeners.get(i)); + } + for (OnLayoutListener listener : mOnLayoutListenersCopy) { + listener.onLayout(this); + } + } + + + public interface OnLayoutListener { + void onLayout(View view); + } } diff --git a/app/src/main/java/com/hippo/scene/UnionCurtain.java b/app/src/main/java/com/hippo/scene/UnionCurtain.java new file mode 100644 index 000000000..cb2dbdfa4 --- /dev/null +++ b/app/src/main/java/com/hippo/scene/UnionCurtain.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +public class UnionCurtain extends Curtain { + + private Curtain mOpenCurtain; + private Curtain mCloseCurtain; + + public UnionCurtain(Curtain openCurtain, Curtain closeCurtain) { + mOpenCurtain = openCurtain; + mCloseCurtain = closeCurtain; + } + + @Override + protected void setPreviousScene(@Nullable Scene pScene) { + super.setPreviousScene(pScene); + + mOpenCurtain.setPreviousScene(pScene); + mCloseCurtain.setPreviousScene(pScene); + } + + @Override + protected boolean needSpecifyPreviousScene() { + return mCloseCurtain.needSpecifyPreviousScene(); + } + + @Override + protected void onRebirth() { + mCloseCurtain.onRebirth(); + } + + @Override + public void open(@NonNull Scene enter, @NonNull Scene exit) { + mOpenCurtain.open(enter, exit); + } + + @Override + public void close(@NonNull Scene enter, @NonNull Scene exit) { + mCloseCurtain.close(enter, exit); + } + + @Override + public void endAnimation() { + mOpenCurtain.endAnimation(); + mCloseCurtain.endAnimation(); + } + + @Override + public boolean isInAnimation() { + return mOpenCurtain.isInAnimation() || mCloseCurtain.isInAnimation(); + } +} diff --git a/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java b/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java index b2b3a57b2..f587a2f26 100644 --- a/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java +++ b/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java @@ -28,7 +28,6 @@ import android.widget.TextView; import com.hippo.ehviewer.R; import com.hippo.rippleold.RippleSalon; import com.hippo.scene.AppbarScene; -import com.hippo.scene.SimpleCurtain; import com.hippo.scene.StageActivity; import com.hippo.widget.recyclerview.EasyRecyclerView; @@ -66,7 +65,7 @@ public class PreferenceHeaderScene extends AppbarScene { if (clazz == null) { return false; } else { - startScene(clazz, null, new SimpleCurtain(SimpleCurtain.DIRECTION_BOTTOM)); + startScene(clazz); return true; } } diff --git a/app/src/main/java/com/hippo/widget/GlobalLayoutSet.java b/app/src/main/java/com/hippo/widget/GlobalLayoutSet.java deleted file mode 100644 index 2dc8617f2..000000000 --- a/app/src/main/java/com/hippo/widget/GlobalLayoutSet.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.widget; - -import android.view.ViewTreeObserver; - -import com.hippo.yorozuya.ViewUtils; - -public class GlobalLayoutSet { - - private OnAllLayoutListener mOnAllLayoutListener; - - private int mSize; - - public void setOnAllLayoutListener(OnAllLayoutListener listener) { - mOnAllLayoutListener = listener; - } - - public void addListenerToObserver(ViewTreeObserver observer) { - LayoutListener ll = new LayoutListener(observer); - observer.addOnGlobalLayoutListener(ll); - mSize++; - } - - public int getSize() { - return mSize; - } - - private class LayoutListener implements ViewTreeObserver.OnGlobalLayoutListener { - private ViewTreeObserver mObserver; - - private LayoutListener(ViewTreeObserver observer) { - mObserver = observer; - } - - @Override - public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(mObserver, this); - - if (--mSize == 0) { - mOnAllLayoutListener.onAllLayout(); - } - } - } - - public interface OnAllLayoutListener { - void onAllLayout(); - } -}