OSDN Git Service

Fix incorrect initial position/scale of opening animations.
authorYuli Huang <yuli@google.com>
Tue, 20 Mar 2012 08:37:05 +0000 (16:37 +0800)
committerYuli Huang <yuli@google.com>
Wed, 21 Mar 2012 09:29:09 +0000 (17:29 +0800)
1. Initial position of opening animation isn't correctly offset if the
position repository isn't properly offset by the action bar height.
2. Initial scale of opening animation should match the thumbnail instead
of using a fixed value 240.
This CL is part of efforts to fix b:6016973.

Change-Id: I620705357ba7594d43685e47488928f9fc93d9f6

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

index c833216..818a2ff 100644 (file)
@@ -19,6 +19,7 @@ package com.android.gallery3d.app;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Vibrator;
@@ -131,6 +132,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
             mAlbumView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
             GalleryUtils.setViewPointMatrix(mMatrix,
                     (right - left) / 2, (bottom - top) / 2, -mUserDistance);
+            // Reset position offset after the layout is changed.
             PositionRepository.getInstance(mActivity).setOffset(
                     0, slotViewTop);
         }
@@ -168,7 +170,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
         mAlbumView.invalidate();
     }
 
-    public void onSingleTapUp(int slotIndex) {
+    private void onSingleTapUp(int slotIndex) {
         MediaItem item = mAlbumDataAdapter.get(slotIndex);
         if (item == null) {
             Log.w(TAG, "item not ready yet, ignore the click");
@@ -185,6 +187,8 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
                 Bundle data = new Bundle();
                 mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
                 data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex);
+                data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT,
+                        getSlotRect(slotIndex));
                 data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
                         mMediaSetPath.toString());
                 data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
@@ -199,6 +203,16 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
         }
     }
 
+    private Rect getSlotRect(int slotIndex) {
+        // Get slot rectangle relative to this root pane.
+        Rect offset = new Rect();
+        mRootPane.getBoundsOf(mAlbumView, offset);
+        Rect r = mAlbumView.getSlotRect(slotIndex);
+        r.offset(offset.left - mAlbumView.getScrollX(),
+                offset.top - mAlbumView.getScrollY());
+        return r;
+    }
+
     private void onGetContent(final MediaItem item) {
         DataManager dm = mActivity.getDataManager();
         Activity activity = (Activity) mActivity;
@@ -315,6 +329,9 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
         super.onResume();
         mIsActive = true;
         setContentPane(mRootPane);
+        // Reset position offset for resuming.
+        PositionRepository.getInstance(mActivity).setOffset(
+                mAlbumView.bounds().left, mAlbumView.bounds().top);
 
         Path path = mMediaSet.getPath();
         boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
index e79a3ae..d00c03c 100644 (file)
@@ -132,6 +132,7 @@ public class AlbumSetPage extends ActivityState implements
             }
 
             mAlbumSetView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
+            // Reset position offset after the layout is changed.
             PositionRepository.getInstance(mActivity).setOffset(
                     0, slotViewTop);
         }
@@ -327,6 +328,9 @@ public class AlbumSetPage extends ActivityState implements
         super.onResume();
         mIsActive = true;
         setContentPane(mRootPane);
+        // Reset position offset for resuming.
+        PositionRepository.getInstance(mActivity).setOffset(
+                mAlbumSetView.bounds().left, mAlbumSetView.bounds().top);
 
         // Set the reload bit here to prevent it exit this page in clearLoadingBit().
         setLoadingBit(BIT_LOADING_RELOAD);
index df5b98a..7daf5df 100644 (file)
@@ -22,6 +22,7 @@ import android.content.ActivityNotFoundException;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -78,6 +79,7 @@ public class PhotoPage extends ActivityState
     public static final String KEY_MEDIA_SET_PATH = "media-set-path";
     public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
     public static final String KEY_INDEX_HINT = "index-hint";
+    public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
 
     private GalleryApp mApplication;
     private SelectionManager mSelectionManager;
@@ -140,6 +142,7 @@ public class PhotoPage extends ActivityState
         protected void onLayout(
                 boolean changed, int left, int top, int right, int bottom) {
             mPhotoView.layout(0, 0, right - left, bottom - top);
+            // Reset position offset after the layout is changed.
             PositionRepository.getInstance(mActivity).setOffset(0, 0);
             int filmStripHeight = 0;
             if (mFilmStripView != null) {
@@ -270,8 +273,10 @@ public class PhotoPage extends ActivityState
             }
         };
 
-        // start the opening animation
-        mPhotoView.setOpenedItem(itemPath);
+        // start the opening animation only if it's not restored.
+        if (restoreState == null) {
+            mPhotoView.setOpenAnimationRect((Rect) data.getParcelable(KEY_OPEN_ANIMATION_RECT));
+        }
     }
 
     // We create a Camera View and a ScreenNail. The two work together
@@ -665,6 +670,10 @@ public class PhotoPage extends ActivityState
         super.onResume();
         mIsActive = true;
         setContentPane(mRootPane);
+        // Reset position offset for resuming.
+        PositionRepository.getInstance(mActivity).setOffset(
+                mPhotoView.bounds().left, mPhotoView.bounds().top);
+
         mModel.resume();
         mPhotoView.resume();
         if (mFilmStripView != null) {
index dee23bd..3ec245f 100644 (file)
@@ -19,14 +19,13 @@ package com.android.gallery3d.ui;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Message;
 import android.view.MotionEvent;
 
 import com.android.gallery3d.R;
 import com.android.gallery3d.app.GalleryActivity;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.ui.PositionRepository.Position;
 
 public class PhotoView extends GLView {
     @SuppressWarnings("unused")
@@ -91,11 +90,9 @@ public class PhotoView extends GLView {
 
     private int mImageRotation;
 
-    private Path mOpenedItemPath;
-    private GalleryActivity mActivity;
+    private Rect mOpenAnimationRect;
 
     public PhotoView(GalleryActivity activity) {
-        mActivity = activity;
         mTileView = new TileImageView(activity);
         addComponent(mTileView);
         Context context = activity.getAndroidContext();
@@ -120,7 +117,7 @@ public class PhotoView extends GLView {
                     case MSG_SHOW_LOADING: {
                         if (mLoadingState == LOADING_INIT) {
                             // We don't need the opening animation
-                            mOpenedItemPath = null;
+                            mOpenAnimationRect = null;
 
                             mLoadingSpinner.startAnimation();
                             mLoadingState = LOADING_TIMEOUT;
@@ -233,7 +230,7 @@ public class PhotoView extends GLView {
             mHandler.removeMessages(MSG_SHOW_LOADING);
             mLoadingState = LOADING_FAIL;
             // We don't want the opening animation after loading failure
-            mOpenedItemPath = null;
+            mOpenAnimationRect = null;
         } else if (mLoadingState != LOADING_INIT) {
             mLoadingState = LOADING_INIT;
             mHandler.removeMessages(MSG_SHOW_LOADING);
@@ -730,24 +727,19 @@ public class PhotoView extends GLView {
         mTileView.prepareTextures();
     }
 
-    public void setOpenedItem(Path itemPath) {
-        mOpenedItemPath = itemPath;
+    public void setOpenAnimationRect(Rect rect) {
+        mOpenAnimationRect = rect;
     }
 
     public void showVideoPlayIcon(boolean show) {
         mShowVideoPlayIcon = show;
     }
 
-    // Returns the position saved by the previous page.
-    public Position retrieveSavedPosition() {
-        if (mOpenedItemPath != null) {
-            Position position = PositionRepository
-                    .getInstance(mActivity).get(
-                    System.identityHashCode(mOpenedItemPath));
-            mOpenedItemPath = null;
-            return position;
-        }
-        return null;
+    // Returns the opening animation rectangle saved by the previous page.
+    public Rect retrieveOpenAnimationRect() {
+        Rect r = mOpenAnimationRect;
+        mOpenAnimationRect = null;
+        return r;
     }
 
     public void openAnimationStarted() {
index 1c9aba8..09fbc17 100644 (file)
 package com.android.gallery3d.ui;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.FloatMath;
 
 import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.ui.PositionRepository.Position;
+import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.util.GalleryUtils;
 
 class PositionController {
@@ -140,14 +141,20 @@ class PositionController {
 
         mScaleMin = getMinimalScale(mImageW, mImageH);
 
-        // Start animation from the saved position if we have one.
-        Position position = mViewer.retrieveSavedPosition();
-        if (position != null) {
-            // The animation starts from 240 pixels and centers at the image
-            // at the saved position.
-            float scale = 240f / Math.min(width, height);
-            mCurrentX = Math.round((mViewW / 2f - position.x) / scale) + mImageW / 2;
-            mCurrentY = Math.round((mViewH / 2f - position.y) / scale) + mImageH / 2;
+        // Start animation from the saved rectangle if we have one.
+        Rect r = mViewer.retrieveOpenAnimationRect();
+        if (r != null) {
+            // The animation starts from the specified rectangle; the image
+            // should be scaled and centered as the thumbnail shown in the
+            // rectangle to minimize janky opening animation. Note: The below
+            // implementation depends on how thumbnails are drawn and placed.
+            float size = MediaItem.getTargetSize(
+                    MediaItem.TYPE_MICROTHUMBNAIL);
+            float scale = (size / Math.min(width, height)) * Math.min(
+                    r.width() / size, r.height() / size);
+
+            mCurrentX = Math.round((mViewW / 2f - r.centerX()) / scale) + mImageW / 2;
+            mCurrentY = Math.round((mViewH / 2f - r.centerY()) / scale) + mImageH / 2;
             mCurrentScale = scale;
             mViewer.openAnimationStarted();
             startSnapback();