PhotoViewActivity.java revision 99f6f3ea0e43d5ac96344a987735fc39485f8f05
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; 19f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 20f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.ActionBar; 21150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport android.app.ActionBar.OnMenuVisibilityListener; 22f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.Activity; 23f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.ActivityManager; 2499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdonimport android.content.Context; 25f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Intent; 26f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.database.Cursor; 27f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.net.Uri; 281abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sappersteinimport android.os.Build; 29f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.os.Bundle; 30f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.os.Handler; 318746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.app.Fragment; 328746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.app.FragmentActivity; 338746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.app.LoaderManager; 348746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.content.Loader; 35f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.support.v4.view.ViewPager.OnPageChangeListener; 3699f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdonimport android.text.TextUtils; 37bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Coppimport android.view.MenuItem; 38f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.View; 39f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 40f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.InterceptType; 41f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.OnInterceptTouchListener; 42f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.adapters.PhotoPagerAdapter; 430c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport com.android.ex.photo.fragments.PhotoViewFragment; 44f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.loaders.PhotoPagerLoader; 45f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.provider.PhotoContract; 46f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 47f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport java.util.HashSet; 48f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport java.util.Set; 49f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 50f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/** 51f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Activity to view the contents of an album. 52f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 538746927a945358bb9e515985a37cac7807261026Martin Hibdonpublic class PhotoViewActivity extends FragmentActivity implements 548746927a945358bb9e515985a37cac7807261026Martin Hibdon LoaderManager.LoaderCallbacks<Cursor>, OnPageChangeListener, OnInterceptTouchListener, 55399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon OnMenuVisibilityListener, PhotoViewCallbacks { 560c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 57f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private final static String STATE_ITEM_KEY = 58f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein "com.google.android.apps.plus.PhotoViewFragment.ITEM"; 59f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private final static String STATE_FULLSCREEN_KEY = 60f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein "com.google.android.apps.plus.PhotoViewFragment.FULLSCREEN"; 61f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 62f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private static final int LOADER_PHOTO_LIST = 1; 63f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 64f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** Count used when the real photo count is unknown [but, may be determined] */ 65f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public static final int ALBUM_COUNT_UNKNOWN = -1; 66f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 67f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** Argument key for the dialog message */ 68f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public static final String KEY_MESSAGE = "dialog_message"; 69f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 70f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public static int sMemoryClass; 71f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 72f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The URI of the photos we're viewing; may be {@code null} */ 73f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private String mPhotosUri; 7499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon /** The URI of the initial photo to display */ 7599f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon private String mInitialPhotoUri; 76f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The index of the currently viewed photo */ 77f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private int mPhotoIndex; 78f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The query projection to use; may be {@code null} */ 79f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private String[] mProjection; 80f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The total number of photos; only valid if {@link #mIsEmpty} is {@code false}. */ 81f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private int mAlbumCount = ALBUM_COUNT_UNKNOWN; 82f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** {@code true} if the view is empty. Otherwise, {@code false}. */ 83f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private boolean mIsEmpty; 8499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon /** the main root view */ 8599f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon protected View mRootView; 86f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The main pager; provides left/right swipe between photos */ 8799f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon protected PhotoViewPager mViewPager; 88f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** Adapter to create pager views */ 8999f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon protected PhotoPagerAdapter mAdapter; 90f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** Whether or not we're in "full screen" mode */ 91f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private boolean mFullScreen; 92f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** The set of listeners wanting full screen state */ 93f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private Set<OnScreenListener> mScreenListeners = new HashSet<OnScreenListener>(); 940c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein /** The set of listeners wanting full screen state */ 950c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein private Set<CursorChangedListener> mCursorListeners = new HashSet<CursorChangedListener>(); 96f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** When {@code true}, restart the loader when the activity becomes active */ 97f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private boolean mRestartLoader; 98f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** Whether or not this activity is paused */ 99f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private boolean mIsPaused = true; 10091dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp /** The maximum scale factor applied to images when they are initially displayed */ 10191dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp private float mMaxInitialScale; 102e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook private final Handler mHandler = new Handler(); 103f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // TODO Find a better way to do this. We basically want the activity to display the 104f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // "loading..." progress until the fragment takes over and shows it's own "loading..." 105f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // progress [located in photo_header_view.xml]. We could potentially have all status displayed 106f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // by the activity, but, that gets tricky when it comes to screen rotation. For now, we 107f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // track the loading by this variable which is fragile and may cause phantom "loading..." 108f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // text. 1091abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein private long mActionBarHideDelayTime; 110f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 11199f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon protected PhotoPagerAdapter createPhotoPagerAdapter(Context context, 11299f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon android.support.v4.app.FragmentManager fm, Cursor c, float maxScale) { 11399f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon return new PhotoPagerAdapter(context, fm, c, maxScale); 11499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 11599f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon 116f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 117f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein protected void onCreate(Bundle savedInstanceState) { 118f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onCreate(savedInstanceState); 119f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 120f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final ActivityManager mgr = (ActivityManager) getApplicationContext(). 121f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein getSystemService(Activity.ACTIVITY_SERVICE); 122f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein sMemoryClass = mgr.getMemoryClass(); 123f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 124f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein Intent mIntent = getIntent(); 125f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 126f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein int currentItem = -1; 127f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (savedInstanceState != null) { 128f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein currentItem = savedInstanceState.getInt(STATE_ITEM_KEY, -1); 129f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mFullScreen = savedInstanceState.getBoolean(STATE_FULLSCREEN_KEY, false); 130f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 131f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 132f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // uri of the photos to view; optional 133f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mIntent.hasExtra(Intents.EXTRA_PHOTOS_URI)) { 134f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotosUri = mIntent.getStringExtra(Intents.EXTRA_PHOTOS_URI); 135f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 136f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 137f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // projection for the query; optional 138f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // I.f not set, the default projection is used. 139f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // This projection must include the columns from the default projection. 140f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mIntent.hasExtra(Intents.EXTRA_PROJECTION)) { 141f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mProjection = mIntent.getStringArrayExtra(Intents.EXTRA_PROJECTION); 142f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else { 143f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mProjection = null; 144f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 145f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 146f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Set the current item from the intent if wasn't in the saved instance 147f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mIntent.hasExtra(Intents.EXTRA_PHOTO_INDEX) && currentItem < 0) { 148f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein currentItem = mIntent.getIntExtra(Intents.EXTRA_PHOTO_INDEX, -1); 149f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 15099f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon if (mIntent.hasExtra(Intents.EXTRA_INITIAL_PHOTO_URI) && currentItem < 0) { 15199f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mInitialPhotoUri = mIntent.getStringExtra(Intents.EXTRA_INITIAL_PHOTO_URI); 15299f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 15391dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp 15491dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp // Set the max initial scale, defaulting to 1x 15591dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp mMaxInitialScale = mIntent.getFloatExtra(Intents.EXTRA_MAX_INITIAL_SCALE, 1.0f); 15691dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp 157f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoIndex = currentItem; 158f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 159f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein setContentView(R.layout.photo_activity_view); 160f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 161f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Create the adapter and add the view pager 16299f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mAdapter = createPhotoPagerAdapter(this, getSupportFragmentManager(), 16399f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon null, mMaxInitialScale); 16499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mRootView = findViewById(R.id.photo_activity_root_view); 165f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mViewPager = (PhotoViewPager) findViewById(R.id.photo_view_pager); 166f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mViewPager.setOnPageChangeListener(this); 167f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mViewPager.setOnInterceptTouchListener(this); 168f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 169f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Kick off the loader 1708746927a945358bb9e515985a37cac7807261026Martin Hibdon getSupportLoaderManager().initLoader(LOADER_PHOTO_LIST, null, this); 171f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 172f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final ActionBar actionBar = getActionBar(); 17399f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon if (actionBar != null) { 17499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon actionBar.setDisplayHomeAsUpEnabled(true); 17599f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mActionBarHideDelayTime = getResources().getInteger( 17699f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon R.integer.action_bar_delay_time_in_millis); 17799f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon actionBar.addOnMenuVisibilityListener(this); 17899f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); 17999f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 180f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 181f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 182f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 183f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein protected void onResume() { 184f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onResume(); 185f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein setFullScreen(mFullScreen, false); 186f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 187f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mIsPaused = false; 188f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mRestartLoader) { 189f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mRestartLoader = false; 1908746927a945358bb9e515985a37cac7807261026Martin Hibdon getSupportLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this); 191f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 192f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 193f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 194f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 195f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein protected void onPause() { 196f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mIsPaused = true; 197f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 198f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onPause(); 199f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 200f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 201f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 202f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onBackPressed() { 203f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // If in full screen mode, toggle mode & eat the 'back' 204f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mFullScreen) { 205f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein toggleFullScreen(); 206f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else { 207f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onBackPressed(); 208f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 209f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 210f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 211f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 212f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onSaveInstanceState(Bundle outState) { 213f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onSaveInstanceState(outState); 214f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 215f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein outState.putInt(STATE_ITEM_KEY, mViewPager.getCurrentItem()); 216f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein outState.putBoolean(STATE_FULLSCREEN_KEY, mFullScreen); 217f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 218f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 219bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp @Override 220bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp public boolean onOptionsItemSelected(MenuItem item) { 221bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp switch (item.getItemId()) { 222bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp case android.R.id.home: 223bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp finish(); 224bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp default: 225bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp return super.onOptionsItemSelected(item); 226bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp } 227bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp } 228bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp 229399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 230f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void addScreenListener(OnScreenListener listener) { 231f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mScreenListeners.add(listener); 232f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 233f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 234399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 235f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void removeScreenListener(OnScreenListener listener) { 236f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mScreenListeners.remove(listener); 237f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 238f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 239399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 2400c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public synchronized void addCursorListener(CursorChangedListener listener) { 2410c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mCursorListeners.add(listener); 2420c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 2430c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 244399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 2450c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public synchronized void removeCursorListener(CursorChangedListener listener) { 2460c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mCursorListeners.remove(listener); 2470c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 2480c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 249399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 250f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean isFragmentFullScreen(Fragment fragment) { 251f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mViewPager == null || mAdapter == null || mAdapter.getCount() == 0) { 252f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return mFullScreen; 253f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 254f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return mFullScreen || (mViewPager.getCurrentItem() != mAdapter.getItemPosition(fragment)); 255f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 256f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 257399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 258f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void toggleFullScreen() { 259f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein setFullScreen(!mFullScreen, true); 260f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 261f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 262f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onPhotoRemoved(long photoId) { 263f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final Cursor data = mAdapter.getCursor(); 264f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (data == null) { 265f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Huh?! How would this happen? 266f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return; 267f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 268f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 269f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final int dataCount = data.getCount(); 270f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (dataCount <= 1) { 271f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein finish(); 272f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return; 273f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 274f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 2758746927a945358bb9e515985a37cac7807261026Martin Hibdon getSupportLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this); 276f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 277f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 278f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 279f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public Loader<Cursor> onCreateLoader(int id, Bundle args) { 280f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (id == LOADER_PHOTO_LIST) { 281f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return new PhotoPagerLoader(this, Uri.parse(mPhotosUri), mProjection); 282f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 283f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return null; 284f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 285f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 286f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 2878746927a945358bb9e515985a37cac7807261026Martin Hibdon public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 288f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final int id = loader.getId(); 289f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (id == LOADER_PHOTO_LIST) { 290f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (data == null || data.getCount() == 0) { 291f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mIsEmpty = true; 292f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else { 293f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mAlbumCount = data.getCount(); 294f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 29599f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon if (mInitialPhotoUri != null) { 29699f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon int index = 0; 29799f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon int uriIndex = data.getColumnIndex(PhotoContract.PhotoViewColumns.URI); 29899f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon while (data.moveToNext()) { 29999f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon String uri = data.getString(uriIndex); 30099f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon if (TextUtils.equals(uri, mInitialPhotoUri)) { 30199f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mInitialPhotoUri = null; 30299f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mPhotoIndex = index; 30399f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon break; 30499f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 30599f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon index++; 30699f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 30799f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 30899f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon 309e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook // We're paused; don't do anything now, we'll get re-invoked 310e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook // when the activity becomes active again 311e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook // TODO(pwestbro): This shouldn't be necessary, as the loader manager should 312e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook // restart the loader 313e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook if (mIsPaused) { 314e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook mRestartLoader = true; 315e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook return; 316e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook } 317e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook mIsEmpty = false; 318e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook 3194a6a7183e0740dfb305a16676c867e182aced7aaAdam Copp mAdapter.swapCursor(data); 32099f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon if (mViewPager.getAdapter() == null) { 32199f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon mViewPager.setAdapter(mAdapter); 32299f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon } 3234a6a7183e0740dfb305a16676c867e182aced7aaAdam Copp notifyCursorListeners(data); 3244a6a7183e0740dfb305a16676c867e182aced7aaAdam Copp 325e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook // set the selected photo 326e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook int itemIndex = mPhotoIndex; 327e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook 328e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook // Use an index of 0 if the index wasn't specified or couldn't be found 329e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook if (itemIndex < 0) { 330e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook itemIndex = 0; 331e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook } 332e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook 333e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook mViewPager.setCurrentItem(itemIndex, false); 334e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook setViewActivated(); 335f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 3362989cf0c8e4b0aee4c9ac2b5384a392fd74cd6a9Paul Westbrook // Update the any action items 3372989cf0c8e4b0aee4c9ac2b5384a392fd74cd6a9Paul Westbrook updateActionItems(); 338f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 339f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 340f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 3418746927a945358bb9e515985a37cac7807261026Martin Hibdon @Override 3428746927a945358bb9e515985a37cac7807261026Martin Hibdon public void onLoaderReset(android.support.v4.content.Loader<Cursor> loader) { 3438746927a945358bb9e515985a37cac7807261026Martin Hibdon // If the loader is reset, remove the reference in the adapter to this cursor 3448746927a945358bb9e515985a37cac7807261026Martin Hibdon // TODO(pwestbro): reenable this when b/7075236 is fixed 3458746927a945358bb9e515985a37cac7807261026Martin Hibdon // mAdapter.swapCursor(null); 3468746927a945358bb9e515985a37cac7807261026Martin Hibdon } 3478746927a945358bb9e515985a37cac7807261026Martin Hibdon 3482989cf0c8e4b0aee4c9ac2b5384a392fd74cd6a9Paul Westbrook protected void updateActionItems() { 3492989cf0c8e4b0aee4c9ac2b5384a392fd74cd6a9Paul Westbrook // Do nothing, but allow extending classes to do work 3502989cf0c8e4b0aee4c9ac2b5384a392fd74cd6a9Paul Westbrook } 3512989cf0c8e4b0aee4c9ac2b5384a392fd74cd6a9Paul Westbrook 3520c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein private synchronized void notifyCursorListeners(Cursor data) { 3530c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein // tell all of the objects listening for cursor changes 3540c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein // that the cursor has changed 3550c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein for (CursorChangedListener listener : mCursorListeners) { 3560c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein listener.onCursorChanged(data); 3570c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 3580c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 3590c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 360f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 361f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 362f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 363f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 364f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 365f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onPageSelected(int position) { 366f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoIndex = position; 367150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein setViewActivated(); 368f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 369f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 370f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 371f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public void onPageScrollStateChanged(int state) { 372f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 373f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 374399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 375f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public boolean isFragmentActive(Fragment fragment) { 376f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mViewPager == null || mAdapter == null) { 377f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return false; 378f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 379f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return mViewPager.getCurrentItem() == mAdapter.getItemPosition(fragment); 380f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 381f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 38299f6f3ea0e43d5ac96344a987735fc39485f8f05Martin Hibdon @Override 3830c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public void onFragmentVisible(PhotoViewFragment fragment) { 384150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein updateActionBar(fragment); 385f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 386f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 387f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 388f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public InterceptType onTouchIntercept(float origX, float origY) { 389f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein boolean interceptLeft = false; 390f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein boolean interceptRight = false; 391f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 392f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein for (OnScreenListener listener : mScreenListeners) { 393f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (!interceptLeft) { 394f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein interceptLeft = listener.onInterceptMoveLeft(origX, origY); 395f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 396f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (!interceptRight) { 397f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein interceptRight = listener.onInterceptMoveRight(origX, origY); 398f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 399f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein listener.onViewActivated(); 400f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 401f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 402f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (interceptLeft) { 403f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (interceptRight) { 404f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return InterceptType.BOTH; 405f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 406f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return InterceptType.LEFT; 407f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else if (interceptRight) { 408f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return InterceptType.RIGHT; 409f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 410f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return InterceptType.NONE; 411f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 412f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 413f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 414f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Updates the title bar according to the value of {@link #mFullScreen}. 415f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 4160ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp protected void setFullScreen(boolean fullScreen, boolean setDelayedRunnable) { 417f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final boolean fullScreenChanged = (fullScreen != mFullScreen); 418f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mFullScreen = fullScreen; 419f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 420f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mFullScreen) { 4211abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein setLightsOutMode(true); 422150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein cancelActionBarHideRunnable(); 423f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else { 4241abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein setLightsOutMode(false); 4251abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein if (setDelayedRunnable) { 426150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein postActionBarHideRunnableWithDelay(); 4271abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } 428f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 429f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 430f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (fullScreenChanged) { 431f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein for (OnScreenListener listener : mScreenListeners) { 4321abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein listener.onFullScreenChanged(mFullScreen); 4331abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } 4341abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } 4351abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } 4361abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein 437150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private void postActionBarHideRunnableWithDelay() { 438e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook mHandler.postDelayed(mActionBarHideRunnable, 439150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein mActionBarHideDelayTime); 440150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 441150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 442150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein private void cancelActionBarHideRunnable() { 443e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook mHandler.removeCallbacks(mActionBarHideRunnable); 444150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 445150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 4467e6995626b551c215bc3064c95b9996af940746aAdam Copp protected void setLightsOutMode(boolean enabled) { 4471abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 4481abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein int flags = enabled 4491abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein ? View.SYSTEM_UI_FLAG_LOW_PROFILE 4501abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein | View.SYSTEM_UI_FLAG_FULLSCREEN 4511abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4521abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 4531abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein : View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4541abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 4551abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein 4561abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein // using mViewPager since we have it and we need a view 4571abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein mViewPager.setSystemUiVisibility(flags); 4581abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } else { 4591abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein final ActionBar actionBar = getActionBar(); 4601abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein if (enabled) { 4611abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein actionBar.hide(); 4621abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } else { 4631abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein actionBar.show(); 464f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 4651abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein int flags = enabled 4661abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein ? View.SYSTEM_UI_FLAG_LOW_PROFILE 4671abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein : View.SYSTEM_UI_FLAG_VISIBLE; 4681abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein mViewPager.setSystemUiVisibility(flags); 469f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 470f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 471f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 4721abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein private Runnable mActionBarHideRunnable = new Runnable() { 4731abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein @Override 4741abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein public void run() { 475b462d1bf5d3833fabbdc38d13f66dadcf6ceda54Adam Copp setFullScreen(true, true); 4761abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein } 4771abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein }; 4781abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein 479399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon @Override 4800c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public void setViewActivated() { 481f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein for (OnScreenListener listener : mScreenListeners) { 482f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein listener.onViewActivated(); 483f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 484f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 485f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 486f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 487f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Adjusts the activity title and subtitle to reflect the photo name and count. 488f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 489150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein protected void updateActionBar(PhotoViewFragment fragment) { 490f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final int position = mViewPager.getCurrentItem() + 1; 49168a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein final String title; 492f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final String subtitle; 493f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final boolean hasAlbumCount = mAlbumCount >= 0; 494f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 495f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final Cursor cursor = getCursorAtProperPosition(); 496f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 497f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (cursor != null) { 498f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final int photoNameIndex = cursor.getColumnIndex(PhotoContract.PhotoViewColumns.NAME); 49968a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein title = cursor.getString(photoNameIndex); 50068a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein } else { 50168a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein title = null; 502f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 503f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 504f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mIsEmpty || !hasAlbumCount || position <= 0) { 505f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein subtitle = null; 506f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } else { 507f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein subtitle = getResources().getString(R.string.photo_view_count, position, mAlbumCount); 508f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 509f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 510f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final ActionBar actionBar = getActionBar(); 51168a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); 51268a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein actionBar.setTitle(title); 513f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein actionBar.setSubtitle(subtitle); 514f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 515f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 516f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 517f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Utility method that will return the cursor that contains the data 518f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * at the current position so that it refers to the current image on screen. 519f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * @return the cursor at the current position or 520f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * null if no cursor exists or if the {@link PhotoViewPager} is null. 521f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 522f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public Cursor getCursorAtProperPosition() { 523f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mViewPager == null) { 524f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return null; 525f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 526f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 527f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final int position = mViewPager.getCurrentItem(); 528f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final Cursor cursor = mAdapter.getCursor(); 529f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 530f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (cursor == null) { 531f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return null; 532f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 533f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 534f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein cursor.moveToPosition(position); 535f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 536f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein return cursor; 537f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 5389007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein 5399007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein public Cursor getCursor() { 5409007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein return (mAdapter == null) ? null : mAdapter.getCursor(); 5419007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein } 542150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein 543150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein @Override 544150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein public void onMenuVisibilityChanged(boolean isVisible) { 545150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein if (isVisible) { 546150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein cancelActionBarHideRunnable(); 547150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } else { 548150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein postActionBarHideRunnableWithDelay(); 549150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 550150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein } 5510ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp 5520ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp protected boolean isFullScreen() { 5530ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp return mFullScreen; 5540ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp } 5550ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp 5560ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp protected void setPhotoIndex(int index) { 5570ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp mPhotoIndex = index; 5580ab3e0cf9cbb5751a276e4c2555640a0e8173b5fAdam Copp } 5598746927a945358bb9e515985a37cac7807261026Martin Hibdon 560f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein} 561