PhotoViewFragment.java revision 150e623129eef49467f1d6f67649e4636a4513f2
1f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/* 2f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Copyright (C) 2011 Google Inc. 3f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Licensed to The Android Open Source Project. 4f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 5f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License"); 6f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * you may not use this file except in compliance with the License. 7f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * You may obtain a copy of the License at 8f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 9f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * http://www.apache.org/licenses/LICENSE-2.0 10f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 11f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software 12f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS, 13f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * See the License for the specific language governing permissions and 15f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * limitations under the License. 16f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 17f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 18f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinpackage com.android.ex.photo.fragments; 19f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 20f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.Activity; 21f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.Fragment; 22150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport android.app.LoaderManager; 23f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.LoaderManager.LoaderCallbacks; 24f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Context; 25f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Intent; 26f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Loader; 270c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport android.database.Cursor; 28f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.graphics.Bitmap; 29f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.os.Bundle; 30f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.util.DisplayMetrics; 31f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.LayoutInflater; 32f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.View; 33f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.View.OnClickListener; 34f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.ViewGroup; 35f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.WindowManager; 369007d640832f674a9d65058a3c2a484c078d239eAndrew Sappersteinimport android.widget.ImageView; 37150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport android.widget.ProgressBar; 38150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport android.widget.TextView; 39f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 40f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.Intents; 41f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.PhotoViewActivity; 420c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport com.android.ex.photo.PhotoViewActivity.CursorChangedListener; 43f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.PhotoViewActivity.OnScreenListener; 44f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.R; 450c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport com.android.ex.photo.adapters.PhotoPagerAdapter; 46f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.loaders.PhotoBitmapLoader; 47f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.util.ImageUtils; 48f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.views.PhotoView; 49150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport com.android.ex.photo.views.ProgressBarWrapper; 50f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 51f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/** 52f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Displays a photo. 53f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 54f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinpublic class PhotoViewFragment extends Fragment implements 550c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein LoaderCallbacks<Bitmap>, OnClickListener, OnScreenListener, CursorChangedListener { 56f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 57f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Interface for components that are internally scrollable left-to-right. 58f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 59f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public static interface HorizontallyScrollable { 60f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 61f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Return {@code true} if the component needs to receive right-to-left 62f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * touch movements. 63f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 64f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * @param origX the raw x coordinate of the initial touch 65f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * @param origY the raw y coordinate of the initial touch 66f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 67f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 68f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean interceptMoveLeft(float origX, float origY); 69f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 70f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 71f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Return {@code true} if the component needs to receive left-to-right 72f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * touch movements. 73f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 74f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * @param origX the raw x coordinate of the initial touch 75f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * @param origY the raw y coordinate of the initial touch 76f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 77f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean interceptMoveRight(float origX, float origY); 78f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 79f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 80f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private final static String STATE_INTENT_KEY = 81f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein "com.android.mail.photo.fragments.PhotoViewFragment.INTENT"; 82f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 83f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Loader IDs 84928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein private final static int LOADER_ID_PHOTO = 1; 85928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein private final static int LOADER_ID_THUMBNAIL = 2; 86f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 87f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The size of the photo */ 88f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public static Integer sPhotoSize; 89f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 90f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The URL of a photo to display */ 91f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private String mResolvedPhotoUri; 92928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein private String mThumbnailUri; 93f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The intent we were launched with */ 94f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private Intent mIntent; 95f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private PhotoViewActivity mCallback; 960c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein private PhotoPagerAdapter mAdapter; 97f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 98f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private PhotoView mPhotoView; 99150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private ImageView mPhotoPreviewImage; 100150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private TextView mEmptyText; 101150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private ImageView mRetryButton; 102150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private ProgressBarWrapper mPhotoProgressBar; 103150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 1040c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein private final int mPosition; 105f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 106f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** Whether or not the fragment should make the photo full-screen */ 107f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private boolean mFullScreen; 108f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 109150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private View mPhotoPreviewAndProgress; 110928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein 111f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public PhotoViewFragment() { 1120c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mPosition = -1; 113f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 114f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 1150c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public PhotoViewFragment(Intent intent, int position, PhotoPagerAdapter adapter) { 116f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mIntent = intent; 1170c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mPosition = position; 1180c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mAdapter = adapter; 119f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 120f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 121f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 122f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onAttach(Activity activity) { 123f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onAttach(activity); 124f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mCallback = (PhotoViewActivity) activity; 125f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mCallback == null) { 126150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein throw new IllegalArgumentException( 127150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein "Activity must be a derived class of PhotoViewActivity"); 128f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 129f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 130f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (sPhotoSize == null) { 131f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final DisplayMetrics metrics = new DisplayMetrics(); 132f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final WindowManager wm = 133f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE); 134f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final ImageUtils.ImageSize imageSize = ImageUtils.sUseImageSize; 135f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein wm.getDefaultDisplay().getMetrics(metrics); 136f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein switch (imageSize) { 137f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein case EXTRA_SMALL: { 138f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Use a photo that's 80% of the "small" size 139f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein sPhotoSize = (Math.min(metrics.heightPixels, metrics.widthPixels) * 800) / 1000; 140f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein break; 141f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 142f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 143f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein case SMALL: 144f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein case NORMAL: 145f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein default: { 146f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein sPhotoSize = Math.min(metrics.heightPixels, metrics.widthPixels); 147f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein break; 148f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 149f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 150f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 151f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 152f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 153f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 154f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onDetach() { 155f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mCallback = null; 156f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onDetach(); 157f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 158f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 159f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 160f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onCreate(Bundle savedInstanceState) { 161f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onCreate(savedInstanceState); 162f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 163f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (savedInstanceState != null) { 164f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mIntent = new Intent().putExtras(savedInstanceState.getBundle(STATE_INTENT_KEY)); 165f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 166f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 167f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mResolvedPhotoUri = mIntent.getStringExtra(Intents.EXTRA_RESOLVED_PHOTO_URI); 168928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein mThumbnailUri = mIntent.getStringExtra(Intents.EXTRA_THUMBNAIL_URI); 169f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 170f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 171f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 172f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public View onCreateView(LayoutInflater inflater, ViewGroup container, 173f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein Bundle savedInstanceState) { 174f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final View view = inflater.inflate(R.layout.photo_fragment_view, container, false); 175f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 176f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView = (PhotoView) view.findViewById(R.id.photo_view); 177f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView.setOnClickListener(this); 178f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView.setFullScreen(mFullScreen, false); 1799007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein mPhotoView.enableImageTransforms(true); 1809007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein 181150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewAndProgress = view.findViewById(R.id.photo_preview); 182150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewImage = (ImageView) view.findViewById(R.id.photo_preview_image); 183150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein final ProgressBar indeterminate = 184150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein (ProgressBar) view.findViewById(R.id.indeterminate_progress); 185150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein final ProgressBar determinate = 186150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein (ProgressBar) view.findViewById(R.id.determinate_progress); 187150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoProgressBar = new ProgressBarWrapper(determinate, indeterminate, true); 188150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mEmptyText = (TextView) view.findViewById(R.id.empty_text); 189150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mRetryButton = (ImageView) view.findViewById(R.id.retry_button); 190f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 191f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Don't call until we've setup the entire view 192f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein setViewVisibility(); 193f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 194f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return view; 195f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 196f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 197f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 198f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onResume() { 199f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mCallback.addScreenListener(this); 2000c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mCallback.addCursorListener(this); 201f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 202f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein getLoaderManager().initLoader(LOADER_ID_PHOTO, null, this); 203f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 204f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onResume(); 205f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 206f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 207f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 208f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onPause() { 209f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onPause(); 2100c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein // Remove listeners 2110c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mCallback.removeCursorListener(this); 212f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mCallback.removeScreenListener(this); 213f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein resetPhotoView(); 214f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 215f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 216f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 217f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onDestroyView() { 218f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Clean up views and other components 219f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mPhotoView != null) { 220f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView.clear(); 221f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView = null; 222f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 223f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 224f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onDestroyView(); 225f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 226f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 227f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 228f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onSaveInstanceState(Bundle outState) { 229f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onSaveInstanceState(outState); 230f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 231f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mIntent != null) { 232f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein outState.putParcelable(STATE_INTENT_KEY, mIntent.getExtras()); 233f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 234f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 235f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 236f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 237f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public Loader<Bitmap> onCreateLoader(int id, Bundle args) { 238928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein switch (id) { 239928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein case LOADER_ID_PHOTO: 240928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein return new PhotoBitmapLoader(getActivity(), mResolvedPhotoUri); 241928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein case LOADER_ID_THUMBNAIL: 242928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein return new PhotoBitmapLoader(getActivity(), mThumbnailUri); 243928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein default: 244928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein return null; 245f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 246f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 247f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 248f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 249f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onLoadFinished(Loader<Bitmap> loader, Bitmap data) { 250f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // If we don't have a view, the fragment has been paused. We'll get the cursor again later. 251f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (getView() == null) { 252f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return; 253f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 254f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 255f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final int id = loader.getId(); 256928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein switch (id) { 257928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein case LOADER_ID_PHOTO: 258928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein if (data == null) { 259928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein getLoaderManager().initLoader(LOADER_ID_THUMBNAIL, null, this); 260150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } else { 261150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein bindPhoto(data); 262150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewAndProgress.setVisibility(View.GONE); 263928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein } 264928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein break; 265928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein case LOADER_ID_THUMBNAIL: 2669007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein if (isPhotoBound()) { 2679007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein return; 268150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } else if (data == null) { 2699007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein // no preview, show default 270150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewImage.setVisibility(View.VISIBLE); 271150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewImage.setImageResource(R.drawable.default_image); 272150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } else { 273150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewImage.setVisibility(View.VISIBLE); 274150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mPhotoPreviewImage.setImageBitmap(data); 275928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein } 276928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein break; 277928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein default: 278928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein break; 279f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 280150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 281150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mCallback.setViewActivated(); 282150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein setViewVisibility(); 283f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 284f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 285f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 286f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Binds an image to the photo view. 287f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 288f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private void bindPhoto(Bitmap bitmap) { 289f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mPhotoView != null) { 290f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView.bindPhoto(bitmap); 291f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 292f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 293f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 294f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 295f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Resets the photo view to it's default state w/ no bound photo. 296f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 297f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private void resetPhotoView() { 298f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mPhotoView != null) { 299f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView.bindPhoto(null); 300f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 301f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 302f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 303f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 304f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onLoaderReset(Loader<Bitmap> loader) { 305f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Do nothing 306f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 307f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 308f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 309f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onClick(View v) { 3101abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein mCallback.toggleFullScreen(); 311f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 312f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 313f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 3141abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein public void onFullScreenChanged(boolean fullScreen) { 315f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein setViewVisibility(); 316f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 317f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 318f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 319f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onViewActivated() { 320f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (!mCallback.isFragmentActive(this)) { 321f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // we're not in the foreground; reset our view 322f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein resetViews(); 323f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else { 324f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mCallback.onFragmentVisible(this); 325f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 326f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 327f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 328f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 329f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Reset the views to their default states 330f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 331f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void resetViews() { 332f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mPhotoView != null) { 333f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoView.resetTransformations(); 334f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 335f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 336f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 337f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 338f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean onInterceptMoveLeft(float origX, float origY) { 339f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (!mCallback.isFragmentActive(this)) { 340f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // we're not in the foreground; don't intercept any touches 341f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return false; 342f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 343f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 344f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return (mPhotoView != null && mPhotoView.interceptMoveLeft(origX, origY)); 345f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 346f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 347f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 348f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean onInterceptMoveRight(float origX, float origY) { 349f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (!mCallback.isFragmentActive(this)) { 350f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // we're not in the foreground; don't intercept any touches 351f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return false; 352f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 353f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 354f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return (mPhotoView != null && mPhotoView.interceptMoveRight(origX, origY)); 355f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 356f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 357f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 358f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Returns {@code true} if a photo has been bound. Otherwise, returns {@code false}. 359f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 360f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean isPhotoBound() { 361150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein return (mPhotoView != null && mPhotoView.isPhotoBound()); 362f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 363f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 364f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 365f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Sets view visibility depending upon whether or not we're in "full screen" mode. 366f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 367f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private void setViewVisibility() { 368f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final boolean fullScreen = mCallback.isFragmentFullScreen(this); 369f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final boolean hide = fullScreen; 370f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 371f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein setFullScreen(hide); 372f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 373f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 374f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 375f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Sets full-screen mode for the views. 376f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 377f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void setFullScreen(boolean fullScreen) { 378f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mFullScreen = fullScreen; 379f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 3800c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 3810c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein @Override 3820c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public void onCursorChanged(Cursor cursor) { 3830c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein if (cursor.moveToPosition(mPosition) && !isPhotoBound()) { 3840c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein final LoaderManager manager = getLoaderManager(); 3850c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein final Loader<Bitmap> fakeLoader = manager.getLoader(LOADER_ID_PHOTO); 3860c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein if (fakeLoader == null) { 3870c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein return; 3880c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 3890c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 3900c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein final PhotoBitmapLoader loader = 3910c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein (PhotoBitmapLoader) fakeLoader; 3920c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mResolvedPhotoUri = mAdapter.getPhotoUri(cursor); 3930c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein loader.setPhotoUri(mResolvedPhotoUri); 3940c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein loader.forceLoad(); 3950c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 3960c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 397150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 398150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein public ProgressBarWrapper getPhotoProgressBar() { 399150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein return mPhotoProgressBar; 400150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 401150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 402150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein public TextView getEmptyText() { 403150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein return mEmptyText; 404150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 405150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 406150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein public ImageView getRetryButton() { 407150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein return mRetryButton; 408150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 409f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein} 410