BrowseSupportFragment.java revision a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48
16193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu/* This file is auto-generated from BrowseFragment.java.  DO NOT MODIFY. */
26193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu
361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/*
461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Copyright (C) 2014 The Android Open Source Project
561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * in compliance with the License. You may obtain a copy of the License at
861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * http://www.apache.org/licenses/LICENSE-2.0
1061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
1161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
1261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
1361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * or implied. See the License for the specific language governing permissions and limitations under
1461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the License.
1561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
1661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupackage android.support.v17.leanback.app;
1761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
182f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v4.app.Fragment;
192f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v4.app.FragmentManager;
202f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v4.app.FragmentManager.BackStackEntry;
212f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.content.res.TypedArray;
222f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.graphics.Color;
232f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.graphics.Rect;
242f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.os.Bundle;
2570acb0c19be3831a2080e4f902324de16bfbf62eTor Norbyeimport android.support.annotation.ColorInt;
2661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.R;
2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionHelper;
2861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionListener;
2961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.BrowseFrameLayout;
301c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnataimport android.support.v17.leanback.widget.ListRow;
312f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v17.leanback.widget.ObjectAdapter;
3261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewClickedListener;
3361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewSelectedListener;
341c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnataimport android.support.v17.leanback.widget.PageRow;
3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Presenter;
3661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.PresenterSelector;
372f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v17.leanback.widget.Row;
388df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Guimport android.support.v17.leanback.widget.RowHeaderPresenter;
3961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter;
40a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnataimport android.support.v17.leanback.widget.ScaleFrameLayout;
4161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.TitleView;
4261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
438e3566285de4ac771d6188f62fe947e23d371a3dKris Giesingimport android.support.v4.view.ViewCompat;
4461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log;
4561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.LayoutInflater;
4661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View;
4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup;
4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup.MarginLayoutParams;
49a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnataimport android.view.ViewTreeObserver;
5061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
511c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnataimport static android.support.v7.widget.RecyclerView.NO_POSITION;
521c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/**
5461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A fragment for creating Leanback browse screens. It is composed of a
5561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * RowsSupportFragment and a HeadersSupportFragment.
5661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>
5761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A BrowseSupportFragment renders the elements of its {@link ObjectAdapter} as a set
5861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of rows in a vertical list. The elements in this adapter must be subclasses
5961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of {@link Row}.
6061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>
6161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * The HeadersSupportFragment can be set to be either shown or hidden by default, or
6261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * may be disabled entirely. See {@link #setHeadersState} for details.
6361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>
6461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * By default the BrowseSupportFragment includes support for returning to the headers
6561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * when the user presses Back. For Activities that customize {@link
666193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu * android.support.v4.app.FragmentActivity#onBackPressed()}, you must disable this default Back key support by
6761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * calling {@link #setHeadersTransitionOnBackEnabled(boolean)} with false and
6861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * use {@link BrowseSupportFragment.BrowseTransitionListener} and
6961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * {@link #startHeadersTransition(boolean)}.
70a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
71a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * The recommended theme to use with a BrowseSupportFragment is
72a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link android.support.v17.leanback.R.style#Theme_Leanback_Browse}.
73a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
7461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
753f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gupublic class BrowseSupportFragment extends BaseSupportFragment {
7661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for saving header show/hide status when backstack is used:
7861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String HEADER_STACK_INDEX = "headerStackIndex";
7961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for saving header show/hide status when backstack is not used:
8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String HEADER_SHOW = "headerShow";
81e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout
8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    final class BackStackListener implements FragmentManager.OnBackStackChangedListener {
8361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mLastEntryCount;
8461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mIndexOfHeadersBackStack;
8561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        BackStackListener() {
8761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLastEntryCount = getFragmentManager().getBackStackEntryCount();
8861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mIndexOfHeadersBackStack = -1;
8961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void load(Bundle savedInstanceState) {
9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (savedInstanceState != null) {
9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mIndexOfHeadersBackStack = savedInstanceState.getInt(HEADER_STACK_INDEX, -1);
9461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mShowingHeaders = mIndexOfHeadersBackStack == -1;
9561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
9661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mShowingHeaders) {
9761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    getFragmentManager().beginTransaction()
9861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            .addToBackStack(mWithHeadersBackStackName).commit();
9961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
10061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
10161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void save(Bundle outState) {
10461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            outState.putInt(HEADER_STACK_INDEX, mIndexOfHeadersBackStack);
10561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onBackStackChanged() {
11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (getFragmentManager() == null) {
11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                Log.w(TAG, "getFragmentManager() is null, stack:", new Exception());
11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return;
11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int count = getFragmentManager().getBackStackEntryCount();
11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // if backstack is growing and last pushed entry is "headers" backstack,
11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // remember the index of the entry.
11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (count > mLastEntryCount) {
11861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                BackStackEntry entry = getFragmentManager().getBackStackEntryAt(count - 1);
11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mWithHeadersBackStackName.equals(entry.getName())) {
12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mIndexOfHeadersBackStack = count - 1;
12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (count < mLastEntryCount) {
12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                // if popped "headers" backstack, initiate the show header transition if needed
12461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mIndexOfHeadersBackStack >= count) {
12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mIndexOfHeadersBackStack = -1;
12661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (!mShowingHeaders) {
12761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        startHeadersTransitionInternal(true);
12861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLastEntryCount = count;
13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
13361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
13461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
13561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
13661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Listener for transitions between browse headers and rows.
13761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
13861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static class BrowseTransitionListener {
13961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        /**
14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * Callback when headers transition starts.
14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *
14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * @param withHeaders True if the transition will result in headers
14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *        being shown, false otherwise.
14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         */
14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onHeadersTransitionStart(boolean withHeaders) {
14661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
14761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        /**
14861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * Callback when headers transition stops.
14961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *
15061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * @param withHeaders True if the transition will result in headers
15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *        being shown, false otherwise.
15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         */
15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onHeadersTransitionStop(boolean withHeaders) {
15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
157aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout    private class SetSelectionRunnable implements Runnable {
158aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        static final int TYPE_INVALID = -1;
159aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        static final int TYPE_INTERNAL_SYNC = 0;
160aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        static final int TYPE_USER_REQUEST = 1;
161aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
162aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private int mPosition;
163aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private int mType;
164aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private boolean mSmooth;
165aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
166aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        SetSelectionRunnable() {
167aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            reset();
168aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
169aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
170aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        void post(int position, int type, boolean smooth) {
171aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // Posting the set selection, rather than calling it immediately, prevents an issue
172aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // with adapter changes.  Example: a row is added before the current selected row;
173aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // first the fast lane view updates its selection, then the rows fragment has that
174aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // new selection propagated immediately; THEN the rows view processes the same adapter
175aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // change and moves the selection again.
176aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            if (type >= mType) {
177aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mPosition = position;
178aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mType = type;
179aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mSmooth = smooth;
180aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mBrowseFrame.removeCallbacks(this);
181aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mBrowseFrame.post(this);
182aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            }
183aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
184aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
185aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        @Override
186aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        public void run() {
187aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            setSelection(mPosition, mSmooth);
188aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            reset();
189aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
190aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
191aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private void reset() {
192aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mPosition = -1;
193aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mType = TYPE_INVALID;
194aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mSmooth = false;
195aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
196aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout    }
197aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
1981c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    /**
1991c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * Interface that defines the interaction between {@link BrowseSupportFragment} and it's main
2001c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * content fragment. The key method is {@link AbstractMainFragmentAdapter#getFragment()},
2011c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * it will be used to get the fragment to be shown in the content section. Clients can
2021c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * provide any implementation of fragment and customize it's interaction with
2031c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * {@link BrowseSupportFragment} by overriding the necessary methods.
2041c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     *
2051c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * <p>
2061c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * Clients are expected to provide
2071c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * an instance of {@link MainSupportFragmentAdapterFactory} which will be responsible for providing
2081c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * implementations of {@link AbstractMainFragmentAdapter} for given content types. Currently
2091c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * we support different types of content - {@link ListRow}, {@link PageRow} or any subtype
2101c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * of {@link Row}. We provide an out of the box adapter implementation for any rows other than
2111c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * {@link PageRow} - {@link RowsSupportFragmentAdapter}.
2121c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     *
2131c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * <p>
2141c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * {@link PageRow} is intended to give full flexibility to developers in terms of Fragment
2151c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * design. Users will have to provide an implementation of {@link AbstractMainFragmentAdapter}
2161c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * and provide that through {@link MainSupportFragmentAdapterFactory}.
2171c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * {@link AbstractMainFragmentAdapter} implementation can supply any fragment and override
2181c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * just those interactions that makes sense.
2191c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     */
2201c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    public static abstract class AbstractMainFragmentAdapter {
221f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        private boolean mScalingEnabled;
2221c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public abstract Fragment getFragment();
2232f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2242f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2252f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * Returns whether its scrolling.
2262f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2271c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public boolean isScrolling() {
2281c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            return false;
2291c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
2302f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2312f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2322f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * Set the visibility of titles/hovercard of browse rows.
2332f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2341c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public void setExpand(boolean expand) {
2351c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
2362f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2372f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2382f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * For rows that willing to participate entrance transition,  this function
2392f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * hide views if afterTransition is true,  show views if afterTransition is false.
2402f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2411c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public void setEntranceTransitionState(boolean state) {
2421c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
2432f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2442f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2452f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * Sets the window alignment and also the pivots for scale operation.
2462f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2471c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public void setAlignment(int windowAlignOffsetFromTop) {
2481c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
2492f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2502f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2512f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * Callback indicating transition prepare start.
2522f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2531c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public boolean onTransitionPrepare() {
2541c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            return false;
2551c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
2562f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2572f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2582f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * Callback indicating transition start.
2592f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2601c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public void onTransitionStart() {
2611c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
2622f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2632f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        /**
2642f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         * Callback indicating transition end.
2652f5ebf3f6f7bb6a24856f389e369b247118ba119susnata         */
2661c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        public void onTransitionEnd() {
2671c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
268f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata
269f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        /**
270f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata         * Returns whether row scaling is enabled.
271f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata         */
272f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        public boolean isScalingEnabled() {
273f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata            return mScalingEnabled;
274f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        }
275f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata
276f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        /**
277f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata         * Sets the row scaling property.
278f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata         */
279f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        public void setScalingEnabled(boolean scalingEnabled) {
280f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata            this.mScalingEnabled = scalingEnabled;
281f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        }
282a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata
283a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
284a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Returns the object responsible for communicating with any fragment containing
285a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * list of rows e.g. {@link RowsSupportFragment}.
286a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * When this method returns null, some of the callbacks would be skipped.
287a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * For {@link PageRow}, this should return null as it doesn't have a list of items.
288a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
289a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public MainFragmentRowsAdapter getRowsAdapter() {
290a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            return null;
291a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
2922f5ebf3f6f7bb6a24856f389e369b247118ba119susnata    }
2932f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
2941c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    /**
295a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * This is used to pass information to {@link RowsSupportFragment}. {@link RowsSupportFragmentAdapter}
296a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * would return an instance to connect the callbacks from {@link BrowseSupportFragment} to
297a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * {@link RowsSupportFragment}.
2981c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     */
299a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    public static class MainFragmentRowsAdapter {
300a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
301a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Set the visibility titles/hover of browse rows.
302a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
303a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public void setAdapter(ObjectAdapter adapter) {
304a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
3051c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
306a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
307a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Sets an item clicked listener on the fragment.
308a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
309a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
310a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
311a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata
312a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
313a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Sets an item selection listener.
314a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
315a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
316a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
317a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata
318a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
319a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Selects a Row and perform an optional task on the Row.
320a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
321a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public void setSelectedPosition(int rowPosition,
322a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata                                        boolean smooth,
323a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata                                        final Presenter.ViewHolderTask rowHolderTask) {
324a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
325a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata
326a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
327a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Selects a Row.
328a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
329a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public void setSelectedPosition(int rowPosition, boolean smooth) {
330a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
331a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata
332a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
333a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Returns the selected position.
334a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
335a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public int getSelectedPosition() {
336a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            return 0;
337a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
338a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    }
3391c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
340a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    private boolean createMainFragment(ObjectAdapter adapter, int position) {
341a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        Object item = null;
342a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        if (adapter == null || adapter.size() == 0) {
343a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        } else {
3441c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            if (position < 0 || position > adapter.size()) {
3451c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                throw new IllegalArgumentException(
3461c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                        String.format("Invalid position %d requested", position));
3471c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            }
348a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            item = adapter.get(position);
349a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
350a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        AbstractMainFragmentAdapter oldAdapter = mMainFragmentAdapter;
351a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        boolean isPageRow = item instanceof PageRow;
3521c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
353a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        if (isPageRow) {
354a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mMainFragmentAdapter = mMainSupportFragmentAdapterFactory.getPageFragmentAdapter(
355a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata                    adapter, position);
356a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        } else {
357a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mMainFragmentAdapter = mMainSupportFragmentAdapterFactory.getRowsSupportFragmentAdapter();
3581c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
359a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        mainFragmentRowsAdapter = isPageRow ? null : mMainFragmentAdapter.getRowsAdapter();
360a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        mMainFragment = mMainFragmentAdapter.getFragment();
361a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        return oldAdapter != mMainFragmentAdapter;
362a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    }
363a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata
364a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    /**
365a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * Factory class for {@link BrowseSupportFragment.AbstractMainFragmentAdapter}. Developers can
366a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * override {@link MainSupportFragmentAdapterFactory#getPageFragmentAdapter(ObjectAdapter, int)}
367a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * method to provide their instance of {@link AbstractMainFragmentAdapter}.
368a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * {@link BrowseSupportFragment} will use this factory to create fragments using
369a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * {@link BrowseSupportFragment.AbstractMainFragmentAdapter#getFragment()} to display on
370a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     * the main content section.
371a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata     */
372a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    public static class MainSupportFragmentAdapterFactory {
373a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        private RowsSupportFragmentAdapter rowsFragmentAdapter;
3741c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
375a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        private final RowsSupportFragmentAdapter getRowsSupportFragmentAdapter() {
3761c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            if (rowsFragmentAdapter == null) {
3771c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                rowsFragmentAdapter = new RowsSupportFragmentAdapter();
3781c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            }
3791c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            return rowsFragmentAdapter;
3801c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
3811c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
382a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        /**
383a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         * Override this method to return an instance of {@link AbstractMainFragmentAdapter}.
384a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata         */
385a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        public AbstractMainFragmentAdapter getPageFragmentAdapter(
386a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata                ObjectAdapter adapter, int position) {
387a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            return null;
388a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
3891c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    }
3902f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
39161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String TAG = "BrowseSupportFragment";
39261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String LB_HEADERS_BACKSTACK = "lbHeadersBackStack_";
39461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static boolean DEBUG = false;
39661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is enabled and shown by default. */
39861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_ENABLED = 1;
39961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
40061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is enabled and hidden by default. */
40161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_HIDDEN = 2;
40261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
40361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is disabled and will never be shown. */
40461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_DISABLED = 3;
40561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
4061c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    private MainSupportFragmentAdapterFactory mMainSupportFragmentAdapterFactory
407a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            = new MainSupportFragmentAdapterFactory();
4081c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    private AbstractMainFragmentAdapter mMainFragmentAdapter;
4091c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    private Fragment mMainFragment;
41061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private HeadersSupportFragment mHeadersSupportFragment;
411a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata    private MainFragmentRowsAdapter mainFragmentRowsAdapter;
41261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
41361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ObjectAdapter mAdapter;
41461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
41561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mHeadersState = HEADERS_ENABLED;
41661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBrandColor = Color.TRANSPARENT;
41761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mBrandColorSet;
41861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
41961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BrowseFrameLayout mBrowseFrame;
420a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    private ScaleFrameLayout mScaleFrameLayout;
42161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mHeadersBackStackEnabled = true;
42261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private String mWithHeadersBackStackName;
42361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mShowingHeaders = true;
42461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mCanShowHeaders = true;
4258e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing    private int mContainerListMarginStart;
42661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mContainerListAlignTop;
427f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata    private boolean mMainFragmentScaleEnabled = true;
42861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mExternalOnItemViewSelectedListener;
42961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewClickedListener mOnItemViewClickedListener;
4301c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    private int mSelectedPosition = 0;
431f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata    private float mScaleFactor;
43261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
43361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private PresenterSelector mHeaderPresenterSelector;
434aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout    private final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
43561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
43661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // transition related:
43761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithHeaders;
43861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithoutHeaders;
439c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private Object mSceneAfterEntranceTransition;
44061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mHeadersTransition;
44161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BackStackListener mBackStackChangedListener;
44261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BrowseTransitionListener mBrowseTransitionListener;
44361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
44461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_TITLE = BrowseSupportFragment.class.getCanonicalName() + ".title";
44561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_BADGE_URI = BrowseSupportFragment.class.getCanonicalName() + ".badge";
44661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_HEADERS_STATE =
44761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        BrowseSupportFragment.class.getCanonicalName() + ".headersState";
44861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
44961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
450a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Creates arguments for a browse fragment.
45161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
45261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param args The Bundle to place arguments into, or null if the method
45361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        should return a new Bundle.
45461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param title The title of the BrowseSupportFragment.
45561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headersState The initial state of the headers of the
45661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        BrowseSupportFragment. Must be one of {@link #HEADERS_ENABLED}, {@link
45761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        #HEADERS_HIDDEN}, or {@link #HEADERS_DISABLED}.
45861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @return A Bundle with the given arguments for creating a BrowseSupportFragment.
45961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
46061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static Bundle createArgs(Bundle args, String title, int headersState) {
46161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args == null) {
46261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            args = new Bundle();
46361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
46461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        args.putString(ARG_TITLE, title);
46561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        args.putInt(ARG_HEADERS_STATE, headersState);
46661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return args;
46761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
46861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
46961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
47061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the brand color for the browse fragment. The brand color is used as
47161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the primary color for UI elements in the browse fragment. For example,
47261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the background color of the headers fragment uses the brand color.
47361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
47461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param color The color to use as the brand color of the fragment.
47561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
47670acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye    public void setBrandColor(@ColorInt int color) {
47761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrandColor = color;
47861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrandColorSet = true;
47961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
48061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeadersSupportFragment != null) {
48161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setBackgroundColor(mBrandColor);
48261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
48361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
48461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
48561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
48661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the brand color for the browse fragment.
48761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * The default is transparent.
48861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
48970acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye    @ColorInt
49061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getBrandColor() {
49161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mBrandColor;
49261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
49361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
49561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the adapter containing the rows for the fragment.
49661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
49761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>The items referenced by the adapter must be be derived from
49861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link Row}. These rows will be used by the rows fragment and the headers
49961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * fragment (if not disabled) to render the browse rows.
50061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
50161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param adapter An ObjectAdapter for the browse rows. All items must
50261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        derive from {@link Row}.
50361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
50461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setAdapter(ObjectAdapter adapter) {
50561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mAdapter = adapter;
5062f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        if (mMainFragment != null) {
507a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setAdapter(adapter);
50861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setAdapter(adapter);
50961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
51061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
51161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5121c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    public void setMainSupportFragmentAdapterFactory(MainSupportFragmentAdapterFactory factory) {
5131c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        this.mMainSupportFragmentAdapterFactory = factory;
5141c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    }
51561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
51661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the adapter containing the rows for the fragment.
51761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
51861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public ObjectAdapter getAdapter() {
51961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mAdapter;
52061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
52161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
52361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item selection listener.
52461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
52561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
52661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExternalOnItemViewSelectedListener = listener;
52761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
52861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
53061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns an item selection listener.
53161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
53261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewSelectedListener getOnItemViewSelectedListener() {
53361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mExternalOnItemViewSelectedListener;
53461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
53561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
53661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
5371c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * Get RowsSupportFragment if it's bound to BrowseSupportFragment or null if either BrowseSupportFragment has
5381c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * not been created yet or a different fragment is bound to it.
5391c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     *
5401c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata     * @return RowsSupportFragment if it's bound to BrowseSupportFragment or null otherwise.
5410d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     */
5420d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    public RowsSupportFragment getRowsSupportFragment() {
5431c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        if (mMainFragment instanceof RowsSupportFragment) {
5441c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            return (RowsSupportFragment) mMainFragment;
5451c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
5461c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
5471c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        return null;
5480d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    }
5490d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu
5500d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    /**
5510d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * Get currently bound HeadersSupportFragment or null if HeadersSupportFragment has not been created yet.
5520d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * @return Currently bound HeadersSupportFragment or null if HeadersSupportFragment has not been created yet.
5530d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     */
5540d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    public HeadersSupportFragment getHeadersSupportFragment() {
5550d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu        return mHeadersSupportFragment;
5560d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    }
5570d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu
5580d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    /**
55961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item clicked listener on the fragment.
56061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * OnItemViewClickedListener will override {@link View.OnClickListener} that
56161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}.
56261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * So in general,  developer should choose one of the listeners but not both.
56361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
56461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
56561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemViewClickedListener = listener;
5661c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        if (mMainFragmentAdapter != null) {
567a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setOnItemViewClickedListener(listener);
56861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
56961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
57061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
57161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
57261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the item Clicked listener.
57361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
57461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewClickedListener getOnItemViewClickedListener() {
57561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemViewClickedListener;
57661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
57761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
57861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
579a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Starts a headers transition.
58061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
58161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>This method will begin a transition to either show or hide the
58261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * headers, depending on the value of withHeaders. If headers are disabled
58361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * for this browse fragment, this method will throw an exception.
58461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
58561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param withHeaders True if the headers should transition to being shown,
58661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        false if the transition should result in headers being hidden.
58761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
58861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void startHeadersTransition(boolean withHeaders) {
58961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (!mCanShowHeaders) {
59061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalStateException("Cannot start headers transition");
59161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
59261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (isInHeadersTransition() || mShowingHeaders == withHeaders) {
59361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
59461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
59561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        startHeadersTransitionInternal(withHeaders);
59661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
59761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
59861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
59961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if the headers transition is currently running.
60061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
60161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isInHeadersTransition() {
60261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersTransition != null;
60361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
60461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
60561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
60661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if headers are shown.
60761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
60861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isShowingHeaders() {
60961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mShowingHeaders;
61061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
61161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
61261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
613a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Sets a listener for browse fragment transitions.
61461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
61561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param listener The listener to call when a browse headers transition
61661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        begins or ends.
61761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
61861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBrowseTransitionListener(BrowseTransitionListener listener) {
61961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseTransitionListener = listener;
62061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
62161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
62261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
623f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     * @deprecated use {@link BrowseSupportFragment#enableMainFragmentScaling(boolean)} instead.
62461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
62561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param enable true to enable row scaling
62661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
62761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void enableRowScaling(boolean enable) {
628f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        enableMainFragmentScaling(enable);
629f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata    }
630f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata
631f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata    /**
632f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     * Enables scaling of main fragment when headers are present. For the page/row fragment,
633f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     * scaling is enabled only when both this method and
634f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     * {@link AbstractMainFragmentAdapter#isScalingEnabled()} are enabled.
635f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     *
636f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     * @param enable true to enable row scaling
637f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata     */
638f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata    public void enableMainFragmentScaling(boolean enable) {
639f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        mMainFragmentScaleEnabled = enable;
64061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
64161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
64261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void startHeadersTransitionInternal(final boolean withHeaders) {
64361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getFragmentManager().isDestroyed()) {
64461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
64561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
64661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mShowingHeaders = withHeaders;
6471c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.onTransitionPrepare();
6481c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.onTransitionStart();
649a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        onExpandTransitionStart(!withHeaders, new Runnable() {
65061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
65161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
652902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu                mHeadersSupportFragment.onTransitionPrepare();
65361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.onTransitionStart();
65461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                createHeadersTransition();
65561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mBrowseTransitionListener != null) {
65661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
65761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
6581c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                TransitionHelper.runTransition(
6591c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                        withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders, mHeadersTransition);
66061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mHeadersBackStackEnabled) {
66161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (!withHeaders) {
66261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        getFragmentManager().beginTransaction()
66361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                                .addToBackStack(mWithHeadersBackStackName).commit();
66461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    } else {
66561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        int index = mBackStackChangedListener.mIndexOfHeadersBackStack;
66661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        if (index >= 0) {
66761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            BackStackEntry entry = getFragmentManager().getBackStackEntryAt(index);
66861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            getFragmentManager().popBackStackImmediate(entry.getId(),
66961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
67061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        }
67161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
67261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
67361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
67461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
67561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
67661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
6770d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    boolean isVerticalScrolling() {
67861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // don't run transition
6791c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        return mHeadersSupportFragment.isScrolling() || mMainFragmentAdapter.isScrolling();
68061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
68161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
682e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout
68361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
68461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new BrowseFrameLayout.OnFocusSearchListener() {
68561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
68661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public View onFocusSearch(View focused, int direction) {
68761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // if headers is running transition,  focus stays
6885ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout            if (mCanShowHeaders && isInHeadersTransition()) {
6895ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout                return focused;
6905ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout            }
69161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction);
6925ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout
693e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (getTitleView() != null && focused != getTitleView() &&
694e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                    direction == View.FOCUS_UP) {
695e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                return getTitleView();
696e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            }
697e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (getTitleView() != null && getTitleView().hasFocus() &&
698e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                    direction == View.FOCUS_DOWN) {
6995ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout                return mCanShowHeaders && mShowingHeaders ?
7001c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                        mHeadersSupportFragment.getVerticalGridView() : mMainFragment.getView();
7015ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout            }
7025ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout
7038e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            boolean isRtl = ViewCompat.getLayoutDirection(focused) == View.LAYOUT_DIRECTION_RTL;
7048e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            int towardStart = isRtl ? View.FOCUS_RIGHT : View.FOCUS_LEFT;
7058e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            int towardEnd = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT;
706e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (mCanShowHeaders && direction == towardStart) {
70761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (isVerticalScrolling() || mShowingHeaders) {
70861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return focused;
70961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
71061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return mHeadersSupportFragment.getVerticalGridView();
7118e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            } else if (direction == towardEnd) {
712e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                if (isVerticalScrolling()) {
71361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return focused;
71461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
7151c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                return mMainFragment.getView();
71661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
71761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return null;
71861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
71961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
72061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
72161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
72261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final BrowseFrameLayout.OnChildFocusListener mOnChildFocusListener =
72361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new BrowseFrameLayout.OnChildFocusListener() {
72461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
72561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
72661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
72728fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            if (getChildFragmentManager().isDestroyed()) {
72828fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu                return true;
72928fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            }
73061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // Make sure not changing focus when requestFocus() is called.
73161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mCanShowHeaders && mShowingHeaders) {
7327fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                if (mHeadersSupportFragment != null && mHeadersSupportFragment.getView() != null &&
7337fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                        mHeadersSupportFragment.getView().requestFocus(direction, previouslyFocusedRect)) {
73461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return true;
73561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
73661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
7371c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            if (mMainFragment != null && mMainFragment.getView() != null &&
7381c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                    mMainFragment.getView().requestFocus(direction, previouslyFocusedRect)) {
73961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return true;
74061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
741e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (getTitleView() != null &&
742e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                    getTitleView().requestFocus(direction, previouslyFocusedRect)) {
7437fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                return true;
7447fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout            }
7457fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout            return false;
7461c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
74761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
74861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
74961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onRequestChildFocus(View child, View focused) {
75028fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            if (getChildFragmentManager().isDestroyed()) {
75128fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu                return;
75228fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            }
75361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (!mCanShowHeaders || isInHeadersTransition()) return;
75428fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            int childId = child.getId();
75561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (childId == R.id.browse_container_dock && mShowingHeaders) {
75661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(false);
75761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (childId == R.id.browse_headers_dock && !mShowingHeaders) {
75861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(true);
75961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
76061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
76161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
76261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
76361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
76461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onSaveInstanceState(Bundle outState) {
765e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        super.onSaveInstanceState(outState);
76661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBackStackChangedListener != null) {
76761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mBackStackChangedListener.save(outState);
76861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
76961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            outState.putBoolean(HEADER_SHOW, mShowingHeaders);
77061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
77161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
77261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
77361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
77461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onCreate(Bundle savedInstanceState) {
77561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onCreate(savedInstanceState);
77661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        TypedArray ta = getActivity().obtainStyledAttributes(R.styleable.LeanbackTheme);
7778e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        mContainerListMarginStart = (int) ta.getDimension(
77846443cb5b092f1d9156342645088eead9da026f6Dake Gu                R.styleable.LeanbackTheme_browseRowsMarginStart, getActivity().getResources()
77946443cb5b092f1d9156342645088eead9da026f6Dake Gu                .getDimensionPixelSize(R.dimen.lb_browse_rows_margin_start));
78061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mContainerListAlignTop = (int) ta.getDimension(
78146443cb5b092f1d9156342645088eead9da026f6Dake Gu                R.styleable.LeanbackTheme_browseRowsMarginTop, getActivity().getResources()
78246443cb5b092f1d9156342645088eead9da026f6Dake Gu                .getDimensionPixelSize(R.dimen.lb_browse_rows_margin_top));
78361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ta.recycle();
78461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
78561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        readArguments(getArguments());
78661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
78734f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout        if (mCanShowHeaders) {
78834f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            if (mHeadersBackStackEnabled) {
78934f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mWithHeadersBackStackName = LB_HEADERS_BACKSTACK + this;
79034f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mBackStackChangedListener = new BackStackListener();
79134f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                getFragmentManager().addOnBackStackChangedListener(mBackStackChangedListener);
79234f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mBackStackChangedListener.load(savedInstanceState);
79334f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            } else {
79434f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                if (savedInstanceState != null) {
79534f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                    mShowingHeaders = savedInstanceState.getBoolean(HEADER_SHOW);
79634f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                }
79734f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            }
79834f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout        }
799a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
800f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        mScaleFactor = getResources().getFraction(R.fraction.lb_browse_rows_scale, 1, 1);
80161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
80261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
80361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
80461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onDestroy() {
80561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBackStackChangedListener != null) {
80661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getFragmentManager().removeOnBackStackChangedListener(mBackStackChangedListener);
80761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
80861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onDestroy();
80961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
81061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
81161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
81261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public View onCreateView(LayoutInflater inflater, ViewGroup container,
81361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            Bundle savedInstanceState) {
814a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        if (getChildFragmentManager().findFragmentById(R.id.scale_frame) == null) {
81561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment = new HeadersSupportFragment();
816a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            createMainFragment(mAdapter, mSelectedPosition);
81761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getChildFragmentManager().beginTransaction()
81861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .replace(R.id.browse_headers_dock, mHeadersSupportFragment)
819a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                    .replace(R.id.scale_frame, mMainFragment)
8201c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                    .commit();
82161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
82261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment = (HeadersSupportFragment) getChildFragmentManager()
823a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                    .findFragmentById(R.id.scale_frame);
8241c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            mMainFragment = getChildFragmentManager()
82561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .findFragmentById(R.id.browse_container_dock);
82661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
82761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
82861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders);
82961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeaderPresenterSelector != null) {
83061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector);
83161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
83261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setAdapter(mAdapter);
8338df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu        mHeadersSupportFragment.setOnHeaderViewSelectedListener(mHeaderViewSelectedListener);
83461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setOnHeaderClickedListener(mHeaderClickedListener);
8352f5ebf3f6f7bb6a24856f389e369b247118ba119susnata
83661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        View root = inflater.inflate(R.layout.lb_browse_fragment, container, false);
83761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
838e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        setTitleView((TitleView) root.findViewById(R.id.browse_title_group));
839e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout
84061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame);
84161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame.setOnChildFocusListener(mOnChildFocusListener);
842e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener);
84361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
844a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mScaleFrameLayout = (ScaleFrameLayout) root.findViewById(R.id.scale_frame);
845a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mScaleFrameLayout.setPivotX(0);
846a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mScaleFrameLayout.setPivotY(mContainerListAlignTop);
847a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
848a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        setupMainFragment();
849a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
85061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBrandColorSet) {
85161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setBackgroundColor(mBrandColor);
85261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
85361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8548403619efebe94666c0615c3fc85080a303acf80Dake Gu        mSceneWithHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
85561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
85661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
85761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                showHeaders(true);
85861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
85961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
8608403619efebe94666c0615c3fc85080a303acf80Dake Gu        mSceneWithoutHeaders =  TransitionHelper.createScene(mBrowseFrame, new Runnable() {
86161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
86261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
86361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                showHeaders(false);
86461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
86561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
8668403619efebe94666c0615c3fc85080a303acf80Dake Gu        mSceneAfterEntranceTransition = TransitionHelper.createScene(mBrowseFrame, new Runnable() {
867c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            @Override
868c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            public void run() {
869c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                setEntranceTransitionEndState();
870c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
871c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        });
87261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return root;
87361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
87461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8751c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    private void setupMainFragment() {
876a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        if (mainFragmentRowsAdapter != null) {
877a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setAdapter(mAdapter);
878a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setOnItemViewSelectedListener(mRowViewSelectedListener);
879a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setOnItemViewClickedListener(mOnItemViewClickedListener);
880a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
8811c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    }
8821c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
88361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void createHeadersTransition() {
8848403619efebe94666c0615c3fc85080a303acf80Dake Gu        mHeadersTransition = TransitionHelper.loadTransition(getActivity(),
8854735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu                mShowingHeaders ?
8864735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu                R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out);
88761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8888403619efebe94666c0615c3fc85080a303acf80Dake Gu        TransitionHelper.addTransitionListener(mHeadersTransition, new TransitionListener() {
88961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
89061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onTransitionStart(Object transition) {
89161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
89261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
89361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onTransitionEnd(Object transition) {
89461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersTransition = null;
8951c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                mMainFragmentAdapter.onTransitionEnd();
89661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.onTransitionEnd();
89761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mShowingHeaders) {
89861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    VerticalGridView headerGridView = mHeadersSupportFragment.getVerticalGridView();
89961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (headerGridView != null && !headerGridView.hasFocus()) {
90061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        headerGridView.requestFocus();
90161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
90261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                } else {
9031c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                    View rowsGridView = mMainFragment.getView();
90461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (rowsGridView != null && !rowsGridView.hasFocus()) {
90561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        rowsGridView.requestFocus();
90661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
90761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
90861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mBrowseTransitionListener != null) {
90961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mBrowseTransitionListener.onHeadersTransitionStop(mShowingHeaders);
91061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
91161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
91261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
91361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
91461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
91561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
91661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the {@link PresenterSelector} used to render the row headers.
91761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
91861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headerPresenterSelector The PresenterSelector that will determine
91961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        the Presenter for each row header.
92061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
92161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setHeaderPresenterSelector(PresenterSelector headerPresenterSelector) {
92261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeaderPresenterSelector = headerPresenterSelector;
92361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeadersSupportFragment != null) {
92461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector);
92561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
92661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
92761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
928c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void setHeadersOnScreen(boolean onScreen) {
929c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        MarginLayoutParams lp;
930c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        View containerList;
93161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList = mHeadersSupportFragment.getView();
93261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        lp = (MarginLayoutParams) containerList.getLayoutParams();
9338e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        lp.setMarginStart(onScreen ? 0 : -mContainerListMarginStart);
93461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList.setLayoutParams(lp);
935c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
93661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
937c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void showHeaders(boolean show) {
938c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (DEBUG) Log.v(TAG, "showHeaders " + show);
939c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mHeadersSupportFragment.setHeadersEnabled(show);
940c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(show);
941a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        expandMainFragment(!show);
942a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    }
943a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
944a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    private void expandMainFragment(boolean expand) {
945a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        MarginLayoutParams params = (MarginLayoutParams) mScaleFrameLayout.getLayoutParams();
946a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        params.leftMargin = !expand ? mContainerListMarginStart : 0;
947a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mScaleFrameLayout.setLayoutParams(params);
948a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mMainFragmentAdapter.setExpand(expand);
949a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
950a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        setMainFragmentAlignment();
951f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        final float scaleFactor = !expand
952f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata                && mMainFragmentScaleEnabled && mMainFragmentAdapter.isScalingEnabled()
953f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata                ? mScaleFactor : 1;
954a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mScaleFrameLayout.setLayoutScaleY(scaleFactor);
955a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mScaleFrameLayout.setChildScale(scaleFactor);
95661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
95761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
95861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private HeadersSupportFragment.OnHeaderClickedListener mHeaderClickedListener =
95961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        new HeadersSupportFragment.OnHeaderClickedListener() {
96061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
961729cbf4cd57c87bcd569db5974c8cbd51a942581Dake Gu            public void onHeaderClicked(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
96261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mCanShowHeaders || !mShowingHeaders || isInHeadersTransition()) {
96361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return;
96461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
96561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(false);
9661c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                mMainFragment.getView().requestFocus();
96761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
96861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
96961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
97061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mRowViewSelectedListener = new OnItemViewSelectedListener() {
97161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
97261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
97361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                RowPresenter.ViewHolder rowViewHolder, Row row) {
9741c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            if (mMainFragment == null) {
9751c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                return;
9761c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            }
9771c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
9781c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            int position = ((RowsSupportFragment) mMainFragment)
9792f5ebf3f6f7bb6a24856f389e369b247118ba119susnata                    .getVerticalGridView().getSelectedPosition();
98061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "row selected position " + position);
98161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            onRowSelected(position);
98261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalOnItemViewSelectedListener != null) {
98361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
98461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        rowViewHolder, row);
98561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
98661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
98761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
98861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9898df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu    private HeadersSupportFragment.OnHeaderViewSelectedListener mHeaderViewSelectedListener =
9908df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu            new HeadersSupportFragment.OnHeaderViewSelectedListener() {
99161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
9928df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu        public void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
99361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int position = mHeadersSupportFragment.getVerticalGridView().getSelectedPosition();
99461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "header selected position " + position);
99561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            onRowSelected(position);
99661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
99761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
99861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
99961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void onRowSelected(int position) {
100061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (position != mSelectedPosition) {
1001aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mSetSelectionRunnable.post(
1002aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                    position, SetSelectionRunnable.TYPE_INTERNAL_SYNC, true);
100361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
100461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (getAdapter() == null || getAdapter().size() == 0 || position == 0) {
1005e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                showTitle(true);
1006e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            } else {
1007e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                showTitle(false);
100861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
100961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
101061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
101161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10123f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    private void setSelection(int position, boolean smooth) {
10131c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        if (position == NO_POSITION) {
10141c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            return;
101561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10161c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
10171c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mHeadersSupportFragment.setSelectedPosition(position, smooth);
10183faa5780307cf10ff0e4a1d89a9ba099cdad2e15susnata
1019a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        if (createMainFragment(mAdapter, position)) {
10201c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            swapBrowseContent(mMainFragment);
1021a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            expandMainFragment(!(mCanShowHeaders && mShowingHeaders));
10221c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            setupMainFragment();
10231c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        }
1024a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        if (mainFragmentRowsAdapter != null) {
1025a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setSelectedPosition(position, smooth);
1026a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
102761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSelectedPosition = position;
102861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
102961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10301c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    private void swapBrowseContent(Fragment fragment) {
1031a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        getChildFragmentManager().beginTransaction().replace(R.id.scale_frame, fragment).commit();
10321c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata    }
10331c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
10343f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    /**
10353f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     * Sets the selected row position with smooth animation.
10363f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     */
10373f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    public void setSelectedPosition(int position) {
10383f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        setSelectedPosition(position, true);
10393f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    }
10403f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu
10413f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    /**
10420d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * Gets position of currently selected row.
10430d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * @return Position of currently selected row.
10440d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     */
10450d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    public int getSelectedPosition() {
10460d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu        return mSelectedPosition;
10470d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    }
10480d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu
10490d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    /**
10503f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     * Sets the selected row position.
10513f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     */
10523f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    public void setSelectedPosition(int position, boolean smooth) {
1053aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        mSetSelectionRunnable.post(
1054aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                position, SetSelectionRunnable.TYPE_USER_REQUEST, smooth);
10553f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    }
10563f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu
10570d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    /**
10580d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * Selects a Row and perform an optional task on the Row. For example
10590d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * <code>setSelectedPosition(10, true, new ListRowPresenterSelectItemViewHolderTask(5))</code>
10600d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * scrolls to 11th row and selects 6th item on that row.  The method will be ignored if
10610d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * RowsSupportFragment has not been created (i.e. before {@link #onCreateView(LayoutInflater,
10620d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * ViewGroup, Bundle)}).
10630d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     *
10640d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * @param rowPosition Which row to select.
10650d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * @param smooth True to scroll to the row, false for no animation.
10660d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * @param rowHolderTask Optional task to perform on the Row.  When the task is not null, headers
10670d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     * fragment will be collapsed.
10680d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu     */
10690d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    public void setSelectedPosition(int rowPosition, boolean smooth,
1070cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu            final Presenter.ViewHolderTask rowHolderTask) {
10711c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        if (mMainSupportFragmentAdapterFactory == null) {
10720d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu            return;
10730d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu        }
10740d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu        if (rowHolderTask != null) {
10750d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu            startHeadersTransition(false);
10760d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu        }
1077a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        if (mainFragmentRowsAdapter != null) {
1078a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            mainFragmentRowsAdapter.setSelectedPosition(rowPosition, smooth, rowHolderTask);
1079a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata        }
10800d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu    }
10810d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu
108261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
108361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onStart() {
108461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onStart();
10852f5ebf3f6f7bb6a24856f389e369b247118ba119susnata        mHeadersSupportFragment.setAlignment(mContainerListAlignTop);
1086a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        setMainFragmentAlignment();
108761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
108861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mCanShowHeaders && mShowingHeaders && mHeadersSupportFragment.getView() != null) {
108961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.getView().requestFocus();
109061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else if ((!mCanShowHeaders || !mShowingHeaders)
10911c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata                && mMainFragment.getView() != null) {
10921c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata            mMainFragment.getView().requestFocus();
109361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10941c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
109561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mCanShowHeaders) {
109661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            showHeaders(mShowingHeaders);
109761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10981c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata
10993f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        if (isEntranceTransitionEnabled()) {
1100c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            setEntranceTransitionStartState();
1101c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
110261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
110361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
1104a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    private void onExpandTransitionStart(boolean expand, final Runnable callback) {
1105a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        if (expand) {
1106a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            callback.run();
1107a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            return;
1108a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        }
1109a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        // Run a "pre" layout when we go non-expand, in order to get the initial
1110a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        // positions of added rows.
1111a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        new ExpandPreLayout(callback, mMainFragmentAdapter).execute();
1112a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    }
1113a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1114a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    private void setMainFragmentAlignment() {
1115a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        int alignOffset = mContainerListAlignTop;
1116f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata        if (mMainFragmentScaleEnabled
1117f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata                && mMainFragmentAdapter.isScalingEnabled()
1118f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata                && mShowingHeaders) {
1119f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata            alignOffset = (int) (alignOffset / mScaleFactor + 0.5f);
1120a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        }
1121a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        mMainFragmentAdapter.setAlignment(alignOffset);
1122a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    }
1123a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
112461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
1125a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Enables/disables headers transition on back key support. This is enabled by
112661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * default. The BrowseSupportFragment will add a back stack entry when headers are
112761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * showing. Running a headers transition when the back key is pressed only
112861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * works when the headers state is {@link #HEADERS_ENABLED} or
112961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link #HEADERS_HIDDEN}.
113061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>
113161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * NOTE: If an Activity has its own onBackPressed() handling, you must
113261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * disable this feature. You may use {@link #startHeadersTransition(boolean)}
113361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * and {@link BrowseTransitionListener} in your own back stack handling.
113461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
113561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public final void setHeadersTransitionOnBackEnabled(boolean headersBackStackEnabled) {
113661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersBackStackEnabled = headersBackStackEnabled;
113761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
113861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
113961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
114061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if headers transition on back key support is enabled.
114161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
114261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public final boolean isHeadersTransitionOnBackEnabled() {
114361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersBackStackEnabled;
114461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
114561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
114661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void readArguments(Bundle args) {
114761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args == null) {
114861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
114961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
115061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args.containsKey(ARG_TITLE)) {
115161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setTitle(args.getString(ARG_TITLE));
115261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
115361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args.containsKey(ARG_HEADERS_STATE)) {
115461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setHeadersState(args.getInt(ARG_HEADERS_STATE));
115561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
115661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
115761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
115861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
115961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the state for the headers column in the browse fragment. Must be one
116061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * of {@link #HEADERS_ENABLED}, {@link #HEADERS_HIDDEN}, or
116161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link #HEADERS_DISABLED}.
116261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
116361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headersState The state of the headers for the browse fragment.
116461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
116561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setHeadersState(int headersState) {
116661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (headersState < HEADERS_ENABLED || headersState > HEADERS_DISABLED) {
116761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalArgumentException("Invalid headers state: " + headersState);
116861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
116961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "setHeadersState " + headersState);
117061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
117161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (headersState != mHeadersState) {
117261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersState = headersState;
117361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            switch (headersState) {
117461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_ENABLED:
117561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = true;
117661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = true;
117761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
117861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_HIDDEN:
117961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = true;
118061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = false;
118161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
118261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_DISABLED:
118361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = false;
118461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = false;
118561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
118661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                default:
118761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    Log.w(TAG, "Unknown headers state: " + headersState);
118861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
118961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
119061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mHeadersSupportFragment != null) {
119161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders);
119261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
119361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
119461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
119561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
119661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
119761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the state of the headers column in the browse fragment.
119861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
119961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getHeadersState() {
120061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersState;
120161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
1202c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
12033f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
12043f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected Object createEntranceTransition() {
12058403619efebe94666c0615c3fc85080a303acf80Dake Gu        return TransitionHelper.loadTransition(getActivity(),
12063f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu                R.transition.lb_browse_entrance_transition);
1207c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1208c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
12093f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
12103f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected void runEntranceTransition(Object entranceTransition) {
12118403619efebe94666c0615c3fc85080a303acf80Dake Gu        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
1212c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1213c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
12143f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
1215902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu    protected void onEntranceTransitionPrepare() {
1216902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu        mHeadersSupportFragment.onTransitionPrepare();
12171c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.onTransitionPrepare();
1218902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu    }
1219902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu
1220902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu    @Override
12213f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected void onEntranceTransitionStart() {
12223f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mHeadersSupportFragment.onTransitionStart();
12231c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.onTransitionStart();
1224c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1225c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
12263f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
12273f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected void onEntranceTransitionEnd() {
12281c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.onTransitionEnd();
12293f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mHeadersSupportFragment.onTransitionEnd();
1230c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1231c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
12323f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    void setSearchOrbViewOnScreen(boolean onScreen) {
1233e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        View searchOrbView = getTitleView().getSearchAffordanceView();
1234c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        MarginLayoutParams lp = (MarginLayoutParams) searchOrbView.getLayoutParams();
12358e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        lp.setMarginStart(onScreen ? 0 : -mContainerListMarginStart);
1236c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        searchOrbView.setLayoutParams(lp);
1237c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1238c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1239c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void setEntranceTransitionStartState() {
1240c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(false);
1241c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setSearchOrbViewOnScreen(false);
12421c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.setEntranceTransitionState(false);
1243c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1244c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1245c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void setEntranceTransitionEndState() {
1246c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(mShowingHeaders);
1247c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setSearchOrbViewOnScreen(true);
12481c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata        mMainFragmentAdapter.setEntranceTransitionState(true);
1249c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1250a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1251a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    private static class ExpandPreLayout implements ViewTreeObserver.OnPreDrawListener {
1252a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1253a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        private final View mView;
1254a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        private final Runnable mCallback;
1255a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        private int mState;
1256a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        private AbstractMainFragmentAdapter mainFragmentAdapter;
1257a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1258a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        final static int STATE_INIT = 0;
1259a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        final static int STATE_FIRST_DRAW = 1;
1260a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        final static int STATE_SECOND_DRAW = 2;
1261a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1262a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        ExpandPreLayout(Runnable callback, AbstractMainFragmentAdapter adapter) {
1263a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mView = adapter.getFragment().getView();
1264a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mCallback = callback;
1265a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mainFragmentAdapter = adapter;
1266a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        }
1267a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1268a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        void execute() {
1269a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mView.getViewTreeObserver().addOnPreDrawListener(this);
1270a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mainFragmentAdapter.setExpand(false);
1271a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            mState = STATE_INIT;
1272a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        }
1273a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata
1274a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        @Override
1275a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        public boolean onPreDraw() {
1276a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata            if (mainFragmentAdapter.getFragment().getView() == null) {
1277a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                mView.getViewTreeObserver().removeOnPreDrawListener(this);
1278a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                return true;
1279a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            }
1280a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            if (mState == STATE_INIT) {
1281a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                mainFragmentAdapter.setExpand(true);
1282a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                mState = STATE_FIRST_DRAW;
1283a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            } else if (mState == STATE_FIRST_DRAW) {
1284a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                mCallback.run();
1285a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                mView.getViewTreeObserver().removeOnPreDrawListener(this);
1286a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata                mState = STATE_SECOND_DRAW;
1287a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            }
1288a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata            return false;
1289a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata        }
1290a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata    }
129161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu}
1292