PhotoViewActivity.java revision e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3
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;
24f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.Fragment;
25f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.LoaderManager.LoaderCallbacks;
26f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Intent;
27f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Loader;
28f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.database.Cursor;
29f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.net.Uri;
301abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sappersteinimport android.os.Build;
31f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.os.Bundle;
32f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.os.Handler;
33f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.support.v4.view.ViewPager.OnPageChangeListener;
34f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.View;
35f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
36f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.InterceptType;
37f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.OnInterceptTouchListener;
38f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.adapters.PhotoPagerAdapter;
390c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport com.android.ex.photo.fragments.PhotoViewFragment;
40f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.loaders.PhotoPagerLoader;
41f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.provider.PhotoContract;
42f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
43f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport java.util.HashSet;
44f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport java.util.Set;
45f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
46f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/**
47f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Activity to view the contents of an album.
48f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */
49f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinpublic class PhotoViewActivity extends Activity implements
50f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        LoaderCallbacks<Cursor>, OnPageChangeListener, OnInterceptTouchListener,
519556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook        OnMenuVisibilityListener {
52f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
53f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
54f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Listener to be invoked for screen events.
55f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
56f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public static interface OnScreenListener {
57f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
58f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        /**
59f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * The full screen state has changed.
60f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         */
611abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        public void onFullScreenChanged(boolean fullScreen);
62f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
63f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        /**
64f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * A new view has been activated and the previous view de-activated.
65f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         */
66f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        public void onViewActivated();
67f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
68f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        /**
69f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * Called when a right-to-left touch move intercept is about to occur.
70f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         *
71f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origX the raw x coordinate of the initial touch
72f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origY the raw y coordinate of the initial touch
73f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @return {@code true} if the touch should be intercepted.
74f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         */
75f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        public boolean onInterceptMoveLeft(float origX, float origY);
76f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
77f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        /**
78f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * Called when a left-to-right touch move intercept is about to occur.
79f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         *
80f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origX the raw x coordinate of the initial touch
81f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origY the raw y coordinate of the initial touch
82f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @return {@code true} if the touch should be intercepted.
83f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         */
84f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        public boolean onInterceptMoveRight(float origX, float origY);
85f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
86f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
870c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    public static interface CursorChangedListener {
880c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        /**
890c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein         * Called when the cursor that contains the photo list data
900c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein         * is updated. Note that there is no guarantee that the cursor
910c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein         * will be at the proper position.
920c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein         * @param cursor the cursor containing the photo list data
930c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein         */
940c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        public void onCursorChanged(Cursor cursor);
950c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    }
960c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein
97f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private final static String STATE_ITEM_KEY =
98f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            "com.google.android.apps.plus.PhotoViewFragment.ITEM";
99f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private final static String STATE_FULLSCREEN_KEY =
100f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            "com.google.android.apps.plus.PhotoViewFragment.FULLSCREEN";
101f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
102f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private static final int LOADER_PHOTO_LIST = 1;
103f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
104f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** Count used when the real photo count is unknown [but, may be determined] */
105f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public static final int ALBUM_COUNT_UNKNOWN = -1;
106f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
107f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** Argument key for the dialog message */
108f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public static final String KEY_MESSAGE = "dialog_message";
109f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
110f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public static int sMemoryClass;
111f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
112f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The URI of the photos we're viewing; may be {@code null} */
113f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private String mPhotosUri;
114f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The index of the currently viewed photo */
115f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private int mPhotoIndex;
116f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The query projection to use; may be {@code null} */
117f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private String[] mProjection;
118f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The total number of photos; only valid if {@link #mIsEmpty} is {@code false}. */
119f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private int mAlbumCount = ALBUM_COUNT_UNKNOWN;
120f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** {@code true} if the view is empty. Otherwise, {@code false}. */
121f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private boolean mIsEmpty;
122f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The main pager; provides left/right swipe between photos */
123f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private PhotoViewPager mViewPager;
124f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** Adapter to create pager views */
125f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private PhotoPagerAdapter mAdapter;
126f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** Whether or not we're in "full screen" mode */
127f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private boolean mFullScreen;
128f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The set of listeners wanting full screen state */
129f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private Set<OnScreenListener> mScreenListeners = new HashSet<OnScreenListener>();
1300c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    /** The set of listeners wanting full screen state */
1310c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    private Set<CursorChangedListener> mCursorListeners = new HashSet<CursorChangedListener>();
132f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** When {@code true}, restart the loader when the activity becomes active */
133f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private boolean mRestartLoader;
134f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** Whether or not this activity is paused */
135f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private boolean mIsPaused = true;
136e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook    private final Handler mHandler = new Handler();
137f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // TODO Find a better way to do this. We basically want the activity to display the
138f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // "loading..." progress until the fragment takes over and shows it's own "loading..."
139f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // progress [located in photo_header_view.xml]. We could potentially have all status displayed
140f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // by the activity, but, that gets tricky when it comes to screen rotation. For now, we
141f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // track the loading by this variable which is fragile and may cause phantom "loading..."
142f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // text.
1431abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    private long mActionBarHideDelayTime;
144f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
145f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
146f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    protected void onCreate(Bundle savedInstanceState) {
147f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onCreate(savedInstanceState);
148f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
149f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final ActivityManager mgr = (ActivityManager) getApplicationContext().
150f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                getSystemService(Activity.ACTIVITY_SERVICE);
151f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        sMemoryClass = mgr.getMemoryClass();
152f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
153f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        Intent mIntent = getIntent();
154f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
155f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        int currentItem = -1;
156f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (savedInstanceState != null) {
157f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            currentItem = savedInstanceState.getInt(STATE_ITEM_KEY, -1);
158f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mFullScreen = savedInstanceState.getBoolean(STATE_FULLSCREEN_KEY, false);
159f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
160f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
161f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // uri of the photos to view; optional
162f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mIntent.hasExtra(Intents.EXTRA_PHOTOS_URI)) {
163f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mPhotosUri = mIntent.getStringExtra(Intents.EXTRA_PHOTOS_URI);
164f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
165f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
166f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // projection for the query; optional
167f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // I.f not set, the default projection is used.
168f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // This projection must include the columns from the default projection.
169f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mIntent.hasExtra(Intents.EXTRA_PROJECTION)) {
170f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mProjection = mIntent.getStringArrayExtra(Intents.EXTRA_PROJECTION);
171f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        } else {
172f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mProjection = null;
173f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
174f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
175f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // Set the current item from the intent if wasn't in the saved instance
176f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mIntent.hasExtra(Intents.EXTRA_PHOTO_INDEX) && currentItem < 0) {
177f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            currentItem = mIntent.getIntExtra(Intents.EXTRA_PHOTO_INDEX, -1);
178f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
179f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mPhotoIndex = currentItem;
180f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
181f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        setContentView(R.layout.photo_activity_view);
182f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
183f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // Create the adapter and add the view pager
184f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mAdapter = new PhotoPagerAdapter(this, getFragmentManager(), null);
185f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
186f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mViewPager = (PhotoViewPager) findViewById(R.id.photo_view_pager);
187f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mViewPager.setAdapter(mAdapter);
188f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mViewPager.setOnPageChangeListener(this);
189f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mViewPager.setOnInterceptTouchListener(this);
190f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
191f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // Kick off the loader
192f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        getLoaderManager().initLoader(LOADER_PHOTO_LIST, null, this);
193f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
194f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final ActionBar actionBar = getActionBar();
195f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        actionBar.setDisplayHomeAsUpEnabled(true);
1961abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        mActionBarHideDelayTime = getResources().getInteger(
1971abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                R.integer.action_bar_delay_time_in_millis);
198150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        actionBar.addOnMenuVisibilityListener(this);
19968a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein        actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
200f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
201f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
202f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
203f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    protected void onResume() {
204f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onResume();
205f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        setFullScreen(mFullScreen, false);
206f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
207f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mIsPaused = false;
208f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mRestartLoader) {
209f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mRestartLoader = false;
210f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            getLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this);
211f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
212f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
213f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
214f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
215f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    protected void onPause() {
216f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mIsPaused = true;
217f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
218f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onPause();
219f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
220f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
221f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
222f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onBackPressed() {
223f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // If in full screen mode, toggle mode & eat the 'back'
224f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mFullScreen) {
225f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            toggleFullScreen();
226f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        } else {
227f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            super.onBackPressed();
228f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
229f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
230f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
231f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
232f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onSaveInstanceState(Bundle outState) {
233f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onSaveInstanceState(outState);
234f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
235f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        outState.putInt(STATE_ITEM_KEY, mViewPager.getCurrentItem());
236f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        outState.putBoolean(STATE_FULLSCREEN_KEY, mFullScreen);
237f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
238f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
239f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void addScreenListener(OnScreenListener listener) {
240f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mScreenListeners.add(listener);
241f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
242f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
243f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void removeScreenListener(OnScreenListener listener) {
244f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mScreenListeners.remove(listener);
245f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
246f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
2470c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    public synchronized void addCursorListener(CursorChangedListener listener) {
2480c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mCursorListeners.add(listener);
2490c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    }
2500c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein
2510c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    public synchronized void removeCursorListener(CursorChangedListener listener) {
2520c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mCursorListeners.remove(listener);
2530c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    }
2540c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein
255f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public boolean isFragmentFullScreen(Fragment fragment) {
256f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mViewPager == null || mAdapter == null || mAdapter.getCount() == 0) {
257f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return mFullScreen;
258f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
259f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return mFullScreen || (mViewPager.getCurrentItem() != mAdapter.getItemPosition(fragment));
260f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
261f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
262f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void toggleFullScreen() {
263f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        setFullScreen(!mFullScreen, true);
264f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
265f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
266f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onPhotoRemoved(long photoId) {
267f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final Cursor data = mAdapter.getCursor();
268f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (data == null) {
269f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            // Huh?! How would this happen?
270f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return;
271f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
272f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
273f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final int dataCount = data.getCount();
274f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (dataCount <= 1) {
275f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            finish();
276f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return;
277f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
278f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
279f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        getLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this);
280f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
281f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
282f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
283f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
284f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (id == LOADER_PHOTO_LIST) {
285f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return new PhotoPagerLoader(this, Uri.parse(mPhotosUri), mProjection);
286f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
287f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return null;
288f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
289f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
290f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
291f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
292f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final int id = loader.getId();
293f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (id == LOADER_PHOTO_LIST) {
294f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            if (data == null || data.getCount() == 0) {
295f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                mIsEmpty = true;
296f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            } else {
297f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                mAlbumCount = data.getCount();
298f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
299e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                // We're paused; don't do anything now, we'll get re-invoked
300e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                // when the activity becomes active again
301e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                // TODO(pwestbro): This shouldn't be necessary, as the loader manager should
302e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                // restart the loader
303e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                if (mIsPaused) {
304e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                    mRestartLoader = true;
305e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                    return;
306e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                }
307e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                mIsEmpty = false;
308e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook
309e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                // set the selected photo
310e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                int itemIndex = mPhotoIndex;
311e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook
312e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                // Use an index of 0 if the index wasn't specified or couldn't be found
313e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                if (itemIndex < 0) {
314e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                    itemIndex = 0;
315e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                }
316e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook
317e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                mAdapter.swapCursor(data);
318e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                notifyCursorListeners(data);
319e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook
320e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                mViewPager.setCurrentItem(itemIndex, false);
321e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook                setViewActivated();
322f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            }
323f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
324f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
325f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
3260c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    private synchronized void notifyCursorListeners(Cursor data) {
3270c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        // tell all of the objects listening for cursor changes
3280c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        // that the cursor has changed
3290c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        for (CursorChangedListener listener : mCursorListeners) {
3300c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            listener.onCursorChanged(data);
3310c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        }
3320c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    }
3330c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein
334f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
335f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onLoaderReset(Loader<Cursor> loader) {
336e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook        // If the loader is reset, remove the reference in the adapter to this cursor
337e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook        // TODO(pwestbro): reenable this when b/7075236 is fixed
338e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook        // mAdapter.swapCursor(null);
339f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
340f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
341f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
342f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
343f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
344f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
345f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
346f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onPageSelected(int position) {
347f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mPhotoIndex = position;
348150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        setViewActivated();
349f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
350f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
351f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
352f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onPageScrollStateChanged(int state) {
353f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
354f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
355f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public boolean isFragmentActive(Fragment fragment) {
356f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mViewPager == null || mAdapter == null) {
357f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return false;
358f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
359f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return mViewPager.getCurrentItem() == mAdapter.getItemPosition(fragment);
360f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
361f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
3620c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    public void onFragmentVisible(PhotoViewFragment fragment) {
363150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        updateActionBar(fragment);
364f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
365f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
366f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
367f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public InterceptType onTouchIntercept(float origX, float origY) {
368f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        boolean interceptLeft = false;
369f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        boolean interceptRight = false;
370f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
371f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        for (OnScreenListener listener : mScreenListeners) {
372f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            if (!interceptLeft) {
373f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                interceptLeft = listener.onInterceptMoveLeft(origX, origY);
374f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            }
375f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            if (!interceptRight) {
376f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                interceptRight = listener.onInterceptMoveRight(origX, origY);
377f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            }
378f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            listener.onViewActivated();
379f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
380f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
381f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (interceptLeft) {
382f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            if (interceptRight) {
383f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                return InterceptType.BOTH;
384f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            }
385f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return InterceptType.LEFT;
386f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        } else if (interceptRight) {
387f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return InterceptType.RIGHT;
388f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
389f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return InterceptType.NONE;
390f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
391f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
392f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
393f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Updates the title bar according to the value of {@link #mFullScreen}.
394f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
3951abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    private void setFullScreen(boolean fullScreen, boolean setDelayedRunnable) {
396f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final boolean fullScreenChanged = (fullScreen != mFullScreen);
397f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mFullScreen = fullScreen;
398f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
399f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mFullScreen) {
4001abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            setLightsOutMode(true);
401150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein            cancelActionBarHideRunnable();
402f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        } else {
4031abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            setLightsOutMode(false);
4041abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            if (setDelayedRunnable) {
405150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                postActionBarHideRunnableWithDelay();
4061abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            }
407f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
408f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
409f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (fullScreenChanged) {
410f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            for (OnScreenListener listener : mScreenListeners) {
4111abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                listener.onFullScreenChanged(mFullScreen);
4121abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            }
4131abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        }
4141abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    }
4151abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein
416150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    private void postActionBarHideRunnableWithDelay() {
417e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook        mHandler.postDelayed(mActionBarHideRunnable,
418150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                mActionBarHideDelayTime);
419150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    }
420150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
421150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    private void cancelActionBarHideRunnable() {
422e6d03190d2b2ec6ea07a59daa7e687c3c383f9c3Paul Westbrook        mHandler.removeCallbacks(mActionBarHideRunnable);
423150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    }
424150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
4251abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    private void setLightsOutMode(boolean enabled) {
4261abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
4271abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            int flags = enabled
4281abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    ? View.SYSTEM_UI_FLAG_LOW_PROFILE
4291abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    | View.SYSTEM_UI_FLAG_FULLSCREEN
4301abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4311abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
4321abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    : View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4331abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
4341abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein
4351abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            // using mViewPager since we have it and we need a view
4361abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            mViewPager.setSystemUiVisibility(flags);
4371abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        } else {
4381abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            final ActionBar actionBar = getActionBar();
4391abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            if (enabled) {
4401abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                actionBar.hide();
4411abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            } else {
4421abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                actionBar.show();
443f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            }
4441abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            int flags = enabled
4451abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    ? View.SYSTEM_UI_FLAG_LOW_PROFILE
4461abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein                    : View.SYSTEM_UI_FLAG_VISIBLE;
4471abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            mViewPager.setSystemUiVisibility(flags);
448f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
449f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
450f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
4511abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    private Runnable mActionBarHideRunnable = new Runnable() {
4521abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        @Override
4531abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        public void run() {
4541abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein            PhotoViewActivity.this.setLightsOutMode(true);
4551abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        }
4561abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    };
4571abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein
4580c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    public void setViewActivated() {
459f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        for (OnScreenListener listener : mScreenListeners) {
460f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            listener.onViewActivated();
461f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
462f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
463f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
464f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
465f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Adjusts the activity title and subtitle to reflect the photo name and count.
466f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
467150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    protected void updateActionBar(PhotoViewFragment fragment) {
468f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final int position = mViewPager.getCurrentItem() + 1;
46968a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein        final String title;
470f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final String subtitle;
471f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final boolean hasAlbumCount = mAlbumCount >= 0;
472f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
473f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final Cursor cursor = getCursorAtProperPosition();
474f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
475f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (cursor != null) {
476f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            final int photoNameIndex = cursor.getColumnIndex(PhotoContract.PhotoViewColumns.NAME);
47768a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein            title = cursor.getString(photoNameIndex);
47868a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein        } else {
47968a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein            title = null;
480f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
481f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
482f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mIsEmpty || !hasAlbumCount || position <= 0) {
483f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            subtitle = null;
484f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        } else {
485f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            subtitle = getResources().getString(R.string.photo_view_count, position, mAlbumCount);
486f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
487f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
488f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final ActionBar actionBar = getActionBar();
48968a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
49068a16aa04f9b98868f4412e7324b0fc292c9d858Andrew Sapperstein        actionBar.setTitle(title);
491f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        actionBar.setSubtitle(subtitle);
492f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
493f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
494f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
495f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Utility method that will return the cursor that contains the data
496f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * at the current position so that it refers to the current image on screen.
497f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * @return the cursor at the current position or
498f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * null if no cursor exists or if the {@link PhotoViewPager} is null.
499f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
500f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public Cursor getCursorAtProperPosition() {
501f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mViewPager == null) {
502f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return null;
503f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
504f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
505f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final int position = mViewPager.getCurrentItem();
506f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final Cursor cursor = mAdapter.getCursor();
507f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
508f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (cursor == null) {
509f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return null;
510f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
511f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
512f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        cursor.moveToPosition(position);
513f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
514f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return cursor;
515f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
5169007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein
5179007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein    public Cursor getCursor() {
5189007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein        return (mAdapter == null) ? null : mAdapter.getCursor();
5199007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein    }
520150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
521150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    @Override
522150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    public void onMenuVisibilityChanged(boolean isVisible) {
523150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        if (isVisible) {
524150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein            cancelActionBarHideRunnable();
525150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        } else {
526150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein            postActionBarHideRunnableWithDelay();
527150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        }
528150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    }
529f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein}
530