11cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein/* 21cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Copyright (C) 2011 Google Inc. 31cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Licensed to The Android Open Source Project. 41cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * 51cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License"); 61cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * you may not use this file except in compliance with the License. 71cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * You may obtain a copy of the License at 81cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * 91cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * http://www.apache.org/licenses/LICENSE-2.0 101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * 111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software 121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS, 131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * See the License for the specific language governing permissions and 151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * limitations under the License. 161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinpackage com.android.ex.photo; 191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.ActionBar; 21509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sappersteinimport android.app.ActionBar.OnMenuVisibilityListener; 221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.Activity; 231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.ActivityManager; 241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.Fragment; 251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.LoaderManager.LoaderCallbacks; 261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.Intent; 271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.Loader; 288f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrookimport android.content.res.Resources; 291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.database.Cursor; 301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.net.Uri; 31b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sappersteinimport android.os.Build; 321cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.os.Bundle; 331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.os.Handler; 341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.support.v4.view.ViewPager.OnPageChangeListener; 351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.view.View; 361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 371cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.InterceptType; 381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.OnInterceptTouchListener; 391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.adapters.PhotoPagerAdapter; 40a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sappersteinimport com.android.ex.photo.fragments.PhotoViewFragment; 411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.loaders.PhotoPagerLoader; 421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.provider.PhotoContract; 431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 441cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport java.util.HashSet; 451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport java.util.Set; 461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein/** 481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Activity to view the contents of an album. 491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinpublic class PhotoViewActivity extends Activity implements 511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein LoaderCallbacks<Cursor>, OnPageChangeListener, OnInterceptTouchListener, 52459c618b574a3d3b6a544267a87c2093bacac20dPaul Westbrook OnMenuVisibilityListener { 531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Listener to be invoked for screen events. 561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public static interface OnScreenListener { 581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * The full screen state has changed. 611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 62b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein public void onFullScreenChanged(boolean fullScreen); 631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * A new view has been activated and the previous view de-activated. 661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onViewActivated(); 681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Called when a right-to-left touch move intercept is about to occur. 711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * 721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @param origX the raw x coordinate of the initial touch 731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @param origY the raw y coordinate of the initial touch 741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @return {@code true} if the touch should be intercepted. 751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public boolean onInterceptMoveLeft(float origX, float origY); 771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Called when a left-to-right touch move intercept is about to occur. 801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * 811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @param origX the raw x coordinate of the initial touch 821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @param origY the raw y coordinate of the initial touch 831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @return {@code true} if the touch should be intercepted. 841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public boolean onInterceptMoveRight(float origX, float origY); 861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 88a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein public static interface CursorChangedListener { 89a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein /** 90a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein * Called when the cursor that contains the photo list data 91a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein * is updated. Note that there is no guarantee that the cursor 92a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein * will be at the proper position. 93a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein * @param cursor the cursor containing the photo list data 94a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein */ 95a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein public void onCursorChanged(Cursor cursor); 96a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein } 97a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein 981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private final static String STATE_ITEM_KEY = 991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein "com.google.android.apps.plus.PhotoViewFragment.ITEM"; 1001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private final static String STATE_FULLSCREEN_KEY = 1011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein "com.google.android.apps.plus.PhotoViewFragment.FULLSCREEN"; 1021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private static final int LOADER_PHOTO_LIST = 1; 1041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** Count used when the real photo count is unknown [but, may be determined] */ 1061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public static final int ALBUM_COUNT_UNKNOWN = -1; 1071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** Argument key for the dialog message */ 1091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public static final String KEY_MESSAGE = "dialog_message"; 1101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public static int sMemoryClass; 1121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** The URI of the photos we're viewing; may be {@code null} */ 1141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private String mPhotosUri; 1151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** The index of the currently viewed photo */ 1161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private int mPhotoIndex; 1171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** The query projection to use; may be {@code null} */ 1181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private String[] mProjection; 1191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** The total number of photos; only valid if {@link #mIsEmpty} is {@code false}. */ 1201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private int mAlbumCount = ALBUM_COUNT_UNKNOWN; 1211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** {@code true} if the view is empty. Otherwise, {@code false}. */ 1221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private boolean mIsEmpty; 1231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** The main pager; provides left/right swipe between photos */ 1241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private PhotoViewPager mViewPager; 1251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** Adapter to create pager views */ 1261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private PhotoPagerAdapter mAdapter; 1271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** Whether or not we're in "full screen" mode */ 1281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private boolean mFullScreen; 1291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** The set of listeners wanting full screen state */ 1301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private Set<OnScreenListener> mScreenListeners = new HashSet<OnScreenListener>(); 131a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein /** The set of listeners wanting full screen state */ 132a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein private Set<CursorChangedListener> mCursorListeners = new HashSet<CursorChangedListener>(); 1331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** When {@code true}, restart the loader when the activity becomes active */ 1341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private boolean mRestartLoader; 1351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** Whether or not this activity is paused */ 1361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein private boolean mIsPaused = true; 137114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook private final Handler mHandler = new Handler(); 1381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // TODO Find a better way to do this. We basically want the activity to display the 1391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // "loading..." progress until the fragment takes over and shows it's own "loading..." 1401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // progress [located in photo_header_view.xml]. We could potentially have all status displayed 1411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // by the activity, but, that gets tricky when it comes to screen rotation. For now, we 1421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // track the loading by this variable which is fragile and may cause phantom "loading..." 1431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // text. 144b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein private long mActionBarHideDelayTime; 1451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 1471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein protected void onCreate(Bundle savedInstanceState) { 1481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein super.onCreate(savedInstanceState); 1491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final ActivityManager mgr = (ActivityManager) getApplicationContext(). 1511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein getSystemService(Activity.ACTIVITY_SERVICE); 1521cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein sMemoryClass = mgr.getMemoryClass(); 1531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein Intent mIntent = getIntent(); 1551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein int currentItem = -1; 1571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (savedInstanceState != null) { 1581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein currentItem = savedInstanceState.getInt(STATE_ITEM_KEY, -1); 1591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mFullScreen = savedInstanceState.getBoolean(STATE_FULLSCREEN_KEY, false); 1601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 1611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // uri of the photos to view; optional 1631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mIntent.hasExtra(Intents.EXTRA_PHOTOS_URI)) { 1641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mPhotosUri = mIntent.getStringExtra(Intents.EXTRA_PHOTOS_URI); 1651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 1661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // projection for the query; optional 1681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // I.f not set, the default projection is used. 1691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // This projection must include the columns from the default projection. 1701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mIntent.hasExtra(Intents.EXTRA_PROJECTION)) { 1711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mProjection = mIntent.getStringArrayExtra(Intents.EXTRA_PROJECTION); 1721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } else { 1731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mProjection = null; 1741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 1751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // Set the current item from the intent if wasn't in the saved instance 1771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mIntent.hasExtra(Intents.EXTRA_PHOTO_INDEX) && currentItem < 0) { 1781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein currentItem = mIntent.getIntExtra(Intents.EXTRA_PHOTO_INDEX, -1); 1791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 1801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mPhotoIndex = currentItem; 1811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein setContentView(R.layout.photo_activity_view); 1831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // Create the adapter and add the view pager 1851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mAdapter = new PhotoPagerAdapter(this, getFragmentManager(), null); 1861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1878f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrook final Resources resources = getResources(); 1881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mViewPager = (PhotoViewPager) findViewById(R.id.photo_view_pager); 1891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mViewPager.setAdapter(mAdapter); 1901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mViewPager.setOnPageChangeListener(this); 1911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mViewPager.setOnInterceptTouchListener(this); 1928f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrook mViewPager.setPageMargin(resources.getDimensionPixelSize(R.dimen.photo_page_margin)); 1931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // Kick off the loader 1951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein getLoaderManager().initLoader(LOADER_PHOTO_LIST, null, this); 1961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 1971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final ActionBar actionBar = getActionBar(); 1981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein actionBar.setDisplayHomeAsUpEnabled(true); 1998f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrook mActionBarHideDelayTime = resources.getInteger(R.integer.action_bar_delay_time_in_millis); 200509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein actionBar.addOnMenuVisibilityListener(this); 20176aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); 2021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 2051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein protected void onResume() { 2061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein super.onResume(); 2071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein setFullScreen(mFullScreen, false); 2081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mIsPaused = false; 2101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mRestartLoader) { 2111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mRestartLoader = false; 2121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein getLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this); 2131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 2171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein protected void onPause() { 2181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mIsPaused = true; 2191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein super.onPause(); 2211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 2241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onBackPressed() { 2251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // If in full screen mode, toggle mode & eat the 'back' 2261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mFullScreen) { 2271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein toggleFullScreen(); 2281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } else { 2291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein super.onBackPressed(); 2301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2311cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2321cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 2341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onSaveInstanceState(Bundle outState) { 2351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein super.onSaveInstanceState(outState); 2361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2371cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein outState.putInt(STATE_ITEM_KEY, mViewPager.getCurrentItem()); 2381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein outState.putBoolean(STATE_FULLSCREEN_KEY, mFullScreen); 2391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void addScreenListener(OnScreenListener listener) { 2421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mScreenListeners.add(listener); 2431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2441cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void removeScreenListener(OnScreenListener listener) { 2461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mScreenListeners.remove(listener); 2471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 249a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein public synchronized void addCursorListener(CursorChangedListener listener) { 250a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein mCursorListeners.add(listener); 251a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein } 252a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein 253a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein public synchronized void removeCursorListener(CursorChangedListener listener) { 254a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein mCursorListeners.remove(listener); 255a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein } 256a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein 2571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public boolean isFragmentFullScreen(Fragment fragment) { 2581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mViewPager == null || mAdapter == null || mAdapter.getCount() == 0) { 2591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return mFullScreen; 2601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return mFullScreen || (mViewPager.getCurrentItem() != mAdapter.getItemPosition(fragment)); 2621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void toggleFullScreen() { 2651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein setFullScreen(!mFullScreen, true); 2661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onPhotoRemoved(long photoId) { 2691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final Cursor data = mAdapter.getCursor(); 2701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (data == null) { 2711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein // Huh?! How would this happen? 2721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return; 2731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final int dataCount = data.getCount(); 2761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (dataCount <= 1) { 2771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein finish(); 2781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return; 2791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein getLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this); 2821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 2851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public Loader<Cursor> onCreateLoader(int id, Bundle args) { 2861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (id == LOADER_PHOTO_LIST) { 2871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return new PhotoPagerLoader(this, Uri.parse(mPhotosUri), mProjection); 2881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return null; 2901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 2911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 2921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 2931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) { 2941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final int id = loader.getId(); 2951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (id == LOADER_PHOTO_LIST) { 2961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (data == null || data.getCount() == 0) { 2971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mIsEmpty = true; 2981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } else { 2991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mAlbumCount = data.getCount(); 3001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 301114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // We're paused; don't do anything now, we'll get re-invoked 302114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // when the activity becomes active again 303114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // TODO(pwestbro): This shouldn't be necessary, as the loader manager should 304114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // restart the loader 305114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook if (mIsPaused) { 306114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook mRestartLoader = true; 307114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook return; 308114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook } 309114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook mIsEmpty = false; 310114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook 311114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // set the selected photo 312114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook int itemIndex = mPhotoIndex; 313114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook 314114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // Use an index of 0 if the index wasn't specified or couldn't be found 315114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook if (itemIndex < 0) { 316114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook itemIndex = 0; 317114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook } 318114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook 319114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook mAdapter.swapCursor(data); 320114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook notifyCursorListeners(data); 321114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook 322114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook mViewPager.setCurrentItem(itemIndex, false); 323114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook setViewActivated(); 3241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3252b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook // Update the any action items 3262b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook updateActionItems(); 3271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3302b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook protected void updateActionItems() { 3312b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook // Do nothing, but allow extending classes to do work 3322b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook } 3332b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook 334a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein private synchronized void notifyCursorListeners(Cursor data) { 335a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein // tell all of the objects listening for cursor changes 336a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein // that the cursor has changed 337a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein for (CursorChangedListener listener : mCursorListeners) { 338a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein listener.onCursorChanged(data); 339a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein } 340a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein } 341a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein 3421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 3431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onLoaderReset(Loader<Cursor> loader) { 344114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // If the loader is reset, remove the reference in the adapter to this cursor 345114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // TODO(pwestbro): reenable this when b/7075236 is fixed 346114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook // mAdapter.swapCursor(null); 3471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 3501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 3511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3521cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 3541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onPageSelected(int position) { 3551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mPhotoIndex = position; 356509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein setViewActivated(); 3571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 3601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public void onPageScrollStateChanged(int state) { 3611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public boolean isFragmentActive(Fragment fragment) { 3641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mViewPager == null || mAdapter == null) { 3651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return false; 3661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return mViewPager.getCurrentItem() == mAdapter.getItemPosition(fragment); 3681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 370a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein public void onFragmentVisible(PhotoViewFragment fragment) { 371509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein updateActionBar(fragment); 3721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein @Override 3751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public InterceptType onTouchIntercept(float origX, float origY) { 3761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein boolean interceptLeft = false; 3771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein boolean interceptRight = false; 3781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein for (OnScreenListener listener : mScreenListeners) { 3801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (!interceptLeft) { 3811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein interceptLeft = listener.onInterceptMoveLeft(origX, origY); 3821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (!interceptRight) { 3841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein interceptRight = listener.onInterceptMoveRight(origX, origY); 3851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein listener.onViewActivated(); 3871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 3891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (interceptLeft) { 3901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (interceptRight) { 3911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return InterceptType.BOTH; 3921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return InterceptType.LEFT; 3941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } else if (interceptRight) { 3951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return InterceptType.RIGHT; 3961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return InterceptType.NONE; 3981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 3991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 4011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Updates the title bar according to the value of {@link #mFullScreen}. 4021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 403b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein private void setFullScreen(boolean fullScreen, boolean setDelayedRunnable) { 4041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final boolean fullScreenChanged = (fullScreen != mFullScreen); 4051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein mFullScreen = fullScreen; 4061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mFullScreen) { 408b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein setLightsOutMode(true); 409509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein cancelActionBarHideRunnable(); 4101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } else { 411b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein setLightsOutMode(false); 412b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein if (setDelayedRunnable) { 413509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein postActionBarHideRunnableWithDelay(); 414b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } 4151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (fullScreenChanged) { 4181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein for (OnScreenListener listener : mScreenListeners) { 419b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein listener.onFullScreenChanged(mFullScreen); 420b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } 421b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } 422b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } 423b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein 424509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein private void postActionBarHideRunnableWithDelay() { 425114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook mHandler.postDelayed(mActionBarHideRunnable, 426509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein mActionBarHideDelayTime); 427509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein } 428509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein 429509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein private void cancelActionBarHideRunnable() { 430114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook mHandler.removeCallbacks(mActionBarHideRunnable); 431509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein } 432509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein 433b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein private void setLightsOutMode(boolean enabled) { 434b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 435b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein int flags = enabled 436b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein ? View.SYSTEM_UI_FLAG_LOW_PROFILE 437b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein | View.SYSTEM_UI_FLAG_FULLSCREEN 438b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 439b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 440b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein : View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 441b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 442b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein 443b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein // using mViewPager since we have it and we need a view 444b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein mViewPager.setSystemUiVisibility(flags); 445b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } else { 446b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein final ActionBar actionBar = getActionBar(); 447b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein if (enabled) { 448b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein actionBar.hide(); 449b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } else { 450b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein actionBar.show(); 4511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 452b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein int flags = enabled 453b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein ? View.SYSTEM_UI_FLAG_LOW_PROFILE 454b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein : View.SYSTEM_UI_FLAG_VISIBLE; 455b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein mViewPager.setSystemUiVisibility(flags); 4561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 459b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein private Runnable mActionBarHideRunnable = new Runnable() { 460b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein @Override 461b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein public void run() { 462b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein PhotoViewActivity.this.setLightsOutMode(true); 463b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein } 464b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein }; 465b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein 466a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein public void setViewActivated() { 4671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein for (OnScreenListener listener : mScreenListeners) { 4681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein listener.onViewActivated(); 4691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 4731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Adjusts the activity title and subtitle to reflect the photo name and count. 4741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 475509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein protected void updateActionBar(PhotoViewFragment fragment) { 4761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final int position = mViewPager.getCurrentItem() + 1; 47776aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein final String title; 4781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final String subtitle; 4791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final boolean hasAlbumCount = mAlbumCount >= 0; 4801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final Cursor cursor = getCursorAtProperPosition(); 4821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (cursor != null) { 4841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final int photoNameIndex = cursor.getColumnIndex(PhotoContract.PhotoViewColumns.NAME); 48576aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein title = cursor.getString(photoNameIndex); 48676aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein } else { 48776aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein title = null; 4881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mIsEmpty || !hasAlbumCount || position <= 0) { 4911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein subtitle = null; 4921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } else { 4931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein subtitle = getResources().getString(R.string.photo_view_count, position, mAlbumCount); 4941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 4951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 4961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final ActionBar actionBar = getActionBar(); 49776aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); 49876aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein actionBar.setTitle(title); 4991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein actionBar.setSubtitle(subtitle); 5001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 5011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 5021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein /** 5031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Utility method that will return the cursor that contains the data 5041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * at the current position so that it refers to the current image on screen. 5051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * @return the cursor at the current position or 5061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * null if no cursor exists or if the {@link PhotoViewPager} is null. 5071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */ 5081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein public Cursor getCursorAtProperPosition() { 5091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (mViewPager == null) { 5101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return null; 5111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 5121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 5131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final int position = mViewPager.getCurrentItem(); 5141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein final Cursor cursor = mAdapter.getCursor(); 5151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 5161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein if (cursor == null) { 5171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return null; 5181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 5191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 5201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein cursor.moveToPosition(position); 5211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein 5221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein return cursor; 5231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein } 5249ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein 5259ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein public Cursor getCursor() { 5269ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein return (mAdapter == null) ? null : mAdapter.getCursor(); 5279ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein } 528509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein 529509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein @Override 530509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein public void onMenuVisibilityChanged(boolean isVisible) { 531509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein if (isVisible) { 532509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein cancelActionBarHideRunnable(); 533509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein } else { 534509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein postActionBarHideRunnableWithDelay(); 535509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein } 536509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein } 5375f0470b259c56dd5df171948d6efd4219a3a17f8Mark Wei 5385f0470b259c56dd5df171948d6efd4219a3a17f8Mark Wei public void onNewPhotoLoaded() { 5395f0470b259c56dd5df171948d6efd4219a3a17f8Mark Wei } 5401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein} 541