OSDN Git Service

Add transition for card deck effect.
authorChih-Chung Chang <chihchung@google.com>
Sun, 6 May 2012 18:29:37 +0000 (02:29 +0800)
committerChih-Chung Chang <chihchung@google.com>
Mon, 7 May 2012 07:37:50 +0000 (15:37 +0800)
Bug 6442785: Controls disappear & preview surface gets warped after deleting just taken video
Bug 6399861: Filmstrip: Pinch-out animation in fullscreen photo > filmstrip should be metaphorically consistent with the stack of cards model
Bug 6429677: Gray shadow shows up when start

Change-Id: I408cf250e67b4def20f5f15621fe57d7845c90f9

src/com/android/gallery3d/app/PhotoPage.java
src/com/android/gallery3d/ui/PhotoView.java
src/com/android/gallery3d/ui/PositionController.java

index 40f49f7..acbaaee 100644 (file)
@@ -447,6 +447,7 @@ public class PhotoPage extends ActivityState implements
     private void onUpPressed() {
         if (mActivity.getStateManager().getStateCount() > 1) {
             super.onBackPressed();
+            return;
         }
 
         if (mOriginalSetPathString == null) return;
index da63e8a..7b7c832 100644 (file)
@@ -533,16 +533,17 @@ public class PhotoView extends GLView {
         }
 
         private void drawTileView(GLCanvas canvas, Rect r) {
-            float scale = mPositionController.getImageScale();
+            float imageScale = mPositionController.getImageScale();
             int viewW = getWidth();
             int viewH = getHeight();
             float cx = r.exactCenterX();
             float cy = r.exactCenterY();
-            float extraScale = 1f;  // extra scaling due to card effect
+            float scale = 1f;  // the scaling factor due to card effect
 
             canvas.save(GLCanvas.SAVE_FLAG_MATRIX | GLCanvas.SAVE_FLAG_ALPHA);
-            boolean wantsCardEffect = CARD_EFFECT && !mFilmMode
-                    && !mIsCamera && !mPictures.get(-1).isCamera();
+            float filmRatio = mPositionController.getFilmRatio();
+            boolean wantsCardEffect = CARD_EFFECT && !mIsCamera
+                    && filmRatio != 1f && !mPictures.get(-1).isCamera();
             if (wantsCardEffect) {
                 // Calculate the move-out progress value.
                 int left = r.left;
@@ -553,32 +554,37 @@ public class PhotoView extends GLView {
                 // We only want to apply the fading animation if the scrolling
                 // movement is to the right.
                 if (progress < 0) {
-                    extraScale = getScrollScale(progress);
-                    scale *= extraScale;
-                    canvas.multiplyAlpha(getScrollAlpha(progress));
+                    scale = getScrollScale(progress);
+                    float alpha = getScrollAlpha(progress);
+                    scale = interpolate(filmRatio, scale, 1f);
+                    alpha = interpolate(filmRatio, alpha, 1f);
 
+                    imageScale *= scale;
+                    canvas.multiplyAlpha(alpha);
+
+                    float cxPage;  // the cx value in page mode
                     if (right - left <= viewW) {
                         // If the picture is narrower than the view, keep it at
                         // the center of the view.
-                        cx = viewW / 2f;
+                        cxPage = viewW / 2f;
                     } else {
                         // If the picture is wider than the view (it's
                         // zoomed-in), keep the left edge of the object align
                         // the the left edge of the view.
-                        cx = (right - left) * extraScale / 2f;
+                        cxPage = (right - left) * scale / 2f;
                     }
+                    cx = interpolate(filmRatio, cxPage, cx);
                 }
             }
 
             // Draw the tile view.
-            setTileViewPosition(cx, cy, viewW, viewH, scale);
+            setTileViewPosition(cx, cy, viewW, viewH, imageScale);
             PhotoView.super.render(canvas);
 
             // Draw the play video icon.
             if (mIsVideo) {
                 canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f));
-                int s = (int) (extraScale *
-                        Math.min(r.width(), r.height()) + 0.5f);
+                int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f);
                 drawVideoPlayIcon(canvas, s);
             }
 
@@ -677,30 +683,31 @@ public class PhotoView extends GLView {
                 mListener.onFullScreenChanged(false);
             }
 
-            boolean wantsCardEffect = CARD_EFFECT && !mFilmMode
-                && (mIndex > 0) && !mPictures.get(0).isCamera();
-
+            float filmRatio = mPositionController.getFilmRatio();
+            boolean wantsCardEffect = CARD_EFFECT && mIndex > 0
+                    && filmRatio != 1f && !mPictures.get(0).isCamera();
             int w = getWidth();
-            int drawW = getRotated(mRotation, r.width(), r.height());
-            int drawH = getRotated(mRotation, r.height(), r.width());
-            int cx = wantsCardEffect ? w / 2 : r.centerX();
+            int cx = wantsCardEffect
+                    ? (int) (interpolate(filmRatio, w / 2, r.centerX()) + 0.5f)
+                    : r.centerX();
             int cy = r.centerY();
-            int flags = GLCanvas.SAVE_FLAG_MATRIX;
-
-            if (wantsCardEffect) flags |= GLCanvas.SAVE_FLAG_ALPHA;
-            canvas.save(flags);
+            canvas.save(GLCanvas.SAVE_FLAG_MATRIX | GLCanvas.SAVE_FLAG_ALPHA);
             canvas.translate(cx, cy);
             if (wantsCardEffect) {
                 float progress = (float) (w / 2 - r.centerX()) / w;
                 progress = Utils.clamp(progress, -1, 1);
                 float alpha = getScrollAlpha(progress);
                 float scale = getScrollScale(progress);
+                alpha = interpolate(filmRatio, alpha, 1f);
+                scale = interpolate(filmRatio, scale, 1f);
                 canvas.multiplyAlpha(alpha);
                 canvas.scale(scale, scale, 1);
             }
             if (mRotation != 0) {
                 canvas.rotate(mRotation, 0, 0, 1);
             }
+            int drawW = getRotated(mRotation, r.width(), r.height());
+            int drawH = getRotated(mRotation, r.height(), r.width());
             mScreenNail.draw(canvas, -drawW / 2, -drawH / 2, drawW, drawH);
             if (mIsVideo) drawVideoPlayIcon(canvas, Math.min(drawW, drawH));
             canvas.restore();
@@ -783,6 +790,10 @@ public class PhotoView extends GLView {
 
         @Override
         public boolean onSingleTapUp(float x, float y) {
+            // We do this in addition to onUp() because we want the snapback of
+            // setFilmMode to happen.
+            mHolding &= ~HOLD_TOUCH_DOWN;
+
             if (mFilmMode && !mDownInScrolling) {
                 switchToHitPicture((int) (x + 0.5f), (int) (y + 0.5f));
                 setFilmMode(false);
@@ -1001,23 +1012,23 @@ public class PhotoView extends GLView {
 
     @Override
     protected void render(GLCanvas canvas) {
-        // Draw next photos
-        for (int i = 1; i <= SCREEN_NAIL_MAX; i++) {
+        float filmRatio = mPositionController.getFilmRatio();
+
+        // Draw next photos. In page mode, we draw only one next photo.
+        int lastPhoto = (filmRatio == 0f) ? 1 : SCREEN_NAIL_MAX;
+        for (int i = lastPhoto; i > 0; i--) {
             Rect r = mPositionController.getPosition(i);
             mPictures.get(i).draw(canvas, r);
-            // In page mode, we draw only one next photo.
-            if (!mFilmMode) break;
         }
 
         // Draw current photo
         mPictures.get(0).draw(canvas, mPositionController.getPosition(0));
 
-        // Draw previous photos
-        for (int i = -1; i >= -SCREEN_NAIL_MAX; i--) {
+        // Draw previous photos. In page mode, we draw only one previous photo.
+        lastPhoto = (filmRatio == 0f) ? -1: -SCREEN_NAIL_MAX;
+        for (int i = -1; i >= lastPhoto; i--) {
             Rect r = mPositionController.getPosition(i);
             mPictures.get(i).draw(canvas, r);
-            // In page mode, we draw only one previous photo.
-            if (!mFilmMode) break;
         }
 
         mPositionController.advanceAnimation();
@@ -1327,6 +1338,13 @@ public class PhotoView extends GLView {
         }
     }
 
+    // Returns an interpolated value for the page/film transition.
+    // When ratio = 0, the result is from.
+    // When ratio = 1, the result is to.
+    private static float interpolate(float ratio, float from, float to) {
+        return from + (to - from) * ratio * ratio;
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     //  Simple public utilities
     ////////////////////////////////////////////////////////////////////////////
index c09ffea..f49a0b7 100644 (file)
@@ -90,8 +90,10 @@ class PositionController {
 
     private Listener mListener;
     private volatile Rect mOpenAnimationRect;
-    private int mViewW = 640;
-    private int mViewH = 480;;
+
+    // Use a large enough value, so we won't see the gray shadown in the beginning.
+    private int mViewW = 1200;
+    private int mViewH = 1200;
 
     // A scaling guesture is in progress.
     private boolean mInScale;
@@ -150,6 +152,7 @@ class PositionController {
     // The gap at the right of a Box i is at index i. The gap at the left of a
     // Box i is at index i - 1.
     private RangeArray<Gap> mGaps = new RangeArray<Gap>(-BOX_MAX, BOX_MAX - 1);
+    private FilmRatio mFilmRatio = new FilmRatio();
 
     // These are only used during moveBox().
     private RangeArray<Box> mTempBoxes = new RangeArray<Box>(-BOX_MAX, BOX_MAX);
@@ -633,6 +636,7 @@ class PositionController {
         for (int i = -BOX_MAX; i < BOX_MAX; i++) {
             mGaps.get(i).startSnapback();
         }
+        mFilmRatio.startSnapback();
         redraw();
     }
 
@@ -653,6 +657,7 @@ class PositionController {
         for (int i = -BOX_MAX; i < BOX_MAX; i++) {
             changed |= mGaps.get(i).advanceAnimation();
         }
+        changed |= mFilmRatio.advanceAnimation();
         if (changed) redraw();
     }
 
@@ -1013,6 +1018,10 @@ class PositionController {
         mPlatform.mFromX = mPlatform.mToX = mPlatform.mCurrentX;
     }
 
+    public float getFilmRatio() {
+        return mFilmRatio.mCurrentRatio;
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     //  Private utilities
     ////////////////////////////////////////////////////////////////////////////
@@ -1047,7 +1056,9 @@ class PositionController {
     }
 
     private float getMaximalScale(Box b) {
-        return mFilmMode ? getMinimalScale(b) : SCALE_LIMIT;
+        if (mFilmMode) return getMinimalScale(b);
+        if (mConstrained && !mConstrainedFrame.isEmpty()) return getMinimalScale(b);
+        return SCALE_LIMIT;
     }
 
     private static boolean isAlmostEqual(float a, float b) {
@@ -1525,4 +1536,42 @@ class PositionController {
             }
         }
     }
+
+    ////////////////////////////////////////////////////////////////////////////
+    //  FilmRatio: represents the progress of film mode change.
+    ////////////////////////////////////////////////////////////////////////////
+    private class FilmRatio extends Animatable {
+        // The film ratio: 1 means switching to film mode is complete, 0 means
+        // switching to page mode is complete.
+        public float mCurrentRatio, mFromRatio, mToRatio;
+
+        @Override
+        public boolean startSnapback() {
+            float target = mFilmMode ? 1f : 0f;
+            if (target == mToRatio) return false;
+            return doAnimation(target, ANIM_KIND_SNAPBACK);
+        }
+
+        // Starts an animation for the film ratio.
+        private boolean doAnimation(float targetRatio, int kind) {
+            mAnimationKind = kind;
+            mFromRatio = mCurrentRatio;
+            mToRatio = targetRatio;
+            mAnimationStartTime = AnimationTime.startTime();
+            mAnimationDuration = ANIM_TIME[mAnimationKind];
+            advanceAnimation();
+            return true;
+        }
+
+        @Override
+        protected boolean interpolate(float progress) {
+            if (progress >= 1) {
+                mCurrentRatio = mToRatio;
+                return true;
+            } else {
+                mCurrentRatio = mFromRatio + progress * (mToRatio - mFromRatio);
+                return (mCurrentRatio == mToRatio);
+            }
+        }
+    }
 }