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;
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);
}
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");
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,
}
}
+ 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;
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) |
}
mAlbumSetView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
+ // Reset position offset after the layout is changed.
PositionRepository.getInstance(mActivity).setOffset(
0, slotViewTop);
}
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);
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;
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;
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) {
}
};
- // 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
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) {
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")
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();
case MSG_SHOW_LOADING: {
if (mLoadingState == LOADING_INIT) {
// We don't need the opening animation
- mOpenedItemPath = null;
+ mOpenAnimationRect = null;
mLoadingSpinner.startAnimation();
mLoadingState = LOADING_TIMEOUT;
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);
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() {
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 {
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();