BrowseSupportFragment.java revision a00bada00bff4a58436a39472ab14ccb7a8f619d
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
1861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.R;
19572ed31d757c2635ea0a5cdd7ec8a33cd16f77b7Dake Guimport android.support.v17.leanback.transition.LeanbackTransitionHelper;
2061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionHelper;
2161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionListener;
2261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.BrowseFrameLayout;
2361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.HorizontalGridView;
2461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ItemBridgeAdapter;
2561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewClickedListener;
2661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewSelectedListener;
2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Presenter;
2861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.PresenterSelector;
298df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Guimport android.support.v17.leanback.widget.RowHeaderPresenter;
3061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter;
3161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.TitleView;
3261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
3361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Row;
3461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ObjectAdapter;
3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.SearchOrbView;
368e3566285de4ac771d6188f62fe947e23d371a3dKris Giesingimport android.support.v4.view.ViewCompat;
3761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log;
3861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.FragmentActivity;
3961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.Fragment;
4061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.FragmentManager;
4161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.FragmentManager.BackStackEntry;
4261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.content.Context;
4361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.content.res.TypedArray;
4461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Bundle;
4561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.LayoutInflater;
4661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View;
4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View.OnClickListener;
4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup;
4961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup.MarginLayoutParams;
50c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Guimport android.view.ViewTreeObserver;
5161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.Color;
5261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.Rect;
5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.drawable.Drawable;
5461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport static android.support.v7.widget.RecyclerView.NO_POSITION;
5561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/**
5761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A fragment for creating Leanback browse screens. It is composed of a
5861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * RowsSupportFragment and a HeadersSupportFragment.
5961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>
6061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A BrowseSupportFragment renders the elements of its {@link ObjectAdapter} as a set
6161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of rows in a vertical list. The elements in this adapter must be subclasses
6261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of {@link Row}.
6361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>
6461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * The HeadersSupportFragment can be set to be either shown or hidden by default, or
6561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * may be disabled entirely. See {@link #setHeadersState} for details.
6661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>
6761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * By default the BrowseSupportFragment includes support for returning to the headers
6861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * when the user presses Back. For Activities that customize {@link
696193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu * android.support.v4.app.FragmentActivity#onBackPressed()}, you must disable this default Back key support by
7061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * calling {@link #setHeadersTransitionOnBackEnabled(boolean)} with false and
7161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * use {@link BrowseSupportFragment.BrowseTransitionListener} and
7261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * {@link #startHeadersTransition(boolean)}.
73a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
74a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * The recommended theme to use with a BrowseSupportFragment is
75a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link android.support.v17.leanback.R.style#Theme_Leanback_Browse}.
76a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
7761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
783f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gupublic class BrowseSupportFragment extends BaseSupportFragment {
7961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for saving header show/hide status when backstack is used:
8161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String HEADER_STACK_INDEX = "headerStackIndex";
8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for saving header show/hide status when backstack is not used:
8361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String HEADER_SHOW = "headerShow";
84e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout
8561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    final class BackStackListener implements FragmentManager.OnBackStackChangedListener {
8761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mLastEntryCount;
8861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mIndexOfHeadersBackStack;
8961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        BackStackListener() {
9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLastEntryCount = getFragmentManager().getBackStackEntryCount();
9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mIndexOfHeadersBackStack = -1;
9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
9461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void load(Bundle savedInstanceState) {
9661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (savedInstanceState != null) {
9761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mIndexOfHeadersBackStack = savedInstanceState.getInt(HEADER_STACK_INDEX, -1);
9861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mShowingHeaders = mIndexOfHeadersBackStack == -1;
9961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
10061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mShowingHeaders) {
10161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    getFragmentManager().beginTransaction()
10261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            .addToBackStack(mWithHeadersBackStackName).commit();
10361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
10461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
10561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void save(Bundle outState) {
10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            outState.putInt(HEADER_STACK_INDEX, mIndexOfHeadersBackStack);
10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onBackStackChanged() {
11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (getFragmentManager() == null) {
11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                Log.w(TAG, "getFragmentManager() is null, stack:", new Exception());
11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return;
11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
11861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int count = getFragmentManager().getBackStackEntryCount();
11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // if backstack is growing and last pushed entry is "headers" backstack,
12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // remember the index of the entry.
12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (count > mLastEntryCount) {
12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                BackStackEntry entry = getFragmentManager().getBackStackEntryAt(count - 1);
12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mWithHeadersBackStackName.equals(entry.getName())) {
12461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mIndexOfHeadersBackStack = count - 1;
12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
12661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (count < mLastEntryCount) {
12761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                // if popped "headers" backstack, initiate the show header transition if needed
12861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mIndexOfHeadersBackStack >= count) {
12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mIndexOfHeadersBackStack = -1;
13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (!mShowingHeaders) {
13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        startHeadersTransitionInternal(true);
13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
13361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
13461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
13561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLastEntryCount = count;
13661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
13761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
13861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
13961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Listener for transitions between browse headers and rows.
14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static class BrowseTransitionListener {
14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        /**
14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * Callback when headers transition starts.
14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *
14661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * @param withHeaders True if the transition will result in headers
14761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *        being shown, false otherwise.
14861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         */
14961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onHeadersTransitionStart(boolean withHeaders) {
15061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        /**
15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * Callback when headers transition stops.
15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *
15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * @param withHeaders True if the transition will result in headers
15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *        being shown, false otherwise.
15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         */
15761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onHeadersTransitionStop(boolean withHeaders) {
15861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
15961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
16061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
161aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout    private class SetSelectionRunnable implements Runnable {
162aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        static final int TYPE_INVALID = -1;
163aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        static final int TYPE_INTERNAL_SYNC = 0;
164aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        static final int TYPE_USER_REQUEST = 1;
165aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
166aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private int mPosition;
167aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private int mType;
168aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private boolean mSmooth;
169aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
170aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        SetSelectionRunnable() {
171aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            reset();
172aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
173aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
174aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        void post(int position, int type, boolean smooth) {
175aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // Posting the set selection, rather than calling it immediately, prevents an issue
176aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // with adapter changes.  Example: a row is added before the current selected row;
177aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // first the fast lane view updates its selection, then the rows fragment has that
178aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // new selection propagated immediately; THEN the rows view processes the same adapter
179aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            // change and moves the selection again.
180aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            if (type >= mType) {
181aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mPosition = position;
182aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mType = type;
183aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mSmooth = smooth;
184aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mBrowseFrame.removeCallbacks(this);
185aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                mBrowseFrame.post(this);
186aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            }
187aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
188aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
189aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        @Override
190aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        public void run() {
191aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            setSelection(mPosition, mSmooth);
192aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            reset();
193aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
194aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
195aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        private void reset() {
196aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mPosition = -1;
197aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mType = TYPE_INVALID;
198aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mSmooth = false;
199aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        }
200aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout    }
201aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout
20261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String TAG = "BrowseSupportFragment";
20361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
20461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String LB_HEADERS_BACKSTACK = "lbHeadersBackStack_";
20561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
20661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static boolean DEBUG = false;
20761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
20861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is enabled and shown by default. */
20961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_ENABLED = 1;
21061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
21161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is enabled and hidden by default. */
21261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_HIDDEN = 2;
21361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
21461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is disabled and will never be shown. */
21561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_DISABLED = 3;
21661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
21761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private RowsSupportFragment mRowsSupportFragment;
21861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private HeadersSupportFragment mHeadersSupportFragment;
21961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
22061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ObjectAdapter mAdapter;
22161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
22261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mHeadersState = HEADERS_ENABLED;
22361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBrandColor = Color.TRANSPARENT;
22461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mBrandColorSet;
22561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
22661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BrowseFrameLayout mBrowseFrame;
22761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mHeadersBackStackEnabled = true;
22861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private String mWithHeadersBackStackName;
22961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mShowingHeaders = true;
23061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mCanShowHeaders = true;
2318e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing    private int mContainerListMarginStart;
23261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mContainerListAlignTop;
23361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mRowScaleEnabled = true;
23461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mExternalOnItemViewSelectedListener;
23561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewClickedListener mOnItemViewClickedListener;
23661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mSelectedPosition = -1;
23761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
23861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private PresenterSelector mHeaderPresenterSelector;
239aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout    private final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
24061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
24161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // transition related:
24261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithHeaders;
24361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithoutHeaders;
244c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private Object mSceneAfterEntranceTransition;
24561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mHeadersTransition;
24661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BackStackListener mBackStackChangedListener;
24761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BrowseTransitionListener mBrowseTransitionListener;
24861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
24961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_TITLE = BrowseSupportFragment.class.getCanonicalName() + ".title";
25061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_BADGE_URI = BrowseSupportFragment.class.getCanonicalName() + ".badge";
25161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_HEADERS_STATE =
25261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        BrowseSupportFragment.class.getCanonicalName() + ".headersState";
25361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
25461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
255a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Creates arguments for a browse fragment.
25661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
25761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param args The Bundle to place arguments into, or null if the method
25861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        should return a new Bundle.
25961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param title The title of the BrowseSupportFragment.
26061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headersState The initial state of the headers of the
26161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        BrowseSupportFragment. Must be one of {@link #HEADERS_ENABLED}, {@link
26261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        #HEADERS_HIDDEN}, or {@link #HEADERS_DISABLED}.
26361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @return A Bundle with the given arguments for creating a BrowseSupportFragment.
26461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
26561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static Bundle createArgs(Bundle args, String title, int headersState) {
26661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args == null) {
26761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            args = new Bundle();
26861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
26961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        args.putString(ARG_TITLE, title);
27061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        args.putInt(ARG_HEADERS_STATE, headersState);
27161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return args;
27261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
27361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
27461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
27561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the brand color for the browse fragment. The brand color is used as
27661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the primary color for UI elements in the browse fragment. For example,
27761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the background color of the headers fragment uses the brand color.
27861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
27961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param color The color to use as the brand color of the fragment.
28061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
28161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBrandColor(int color) {
28261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrandColor = color;
28361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrandColorSet = true;
28461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
28561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeadersSupportFragment != null) {
28661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setBackgroundColor(mBrandColor);
28761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
28861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
28961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
29061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
29161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the brand color for the browse fragment.
29261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * The default is transparent.
29361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
29461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getBrandColor() {
29561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mBrandColor;
29661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
29761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
29861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
29961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the adapter containing the rows for the fragment.
30061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
30161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>The items referenced by the adapter must be be derived from
30261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link Row}. These rows will be used by the rows fragment and the headers
30361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * fragment (if not disabled) to render the browse rows.
30461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
30561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param adapter An ObjectAdapter for the browse rows. All items must
30661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        derive from {@link Row}.
30761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
30861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setAdapter(ObjectAdapter adapter) {
30961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mAdapter = adapter;
31061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
31161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.setAdapter(adapter);
31261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setAdapter(adapter);
31361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
31461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
31561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
31661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
31761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the adapter containing the rows for the fragment.
31861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
31961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public ObjectAdapter getAdapter() {
32061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mAdapter;
32161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
32261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
32361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
32461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item selection listener.
32561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
32661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
32761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExternalOnItemViewSelectedListener = listener;
32861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
32961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
33061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
33161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns an item selection listener.
33261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
33361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewSelectedListener getOnItemViewSelectedListener() {
33461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mExternalOnItemViewSelectedListener;
33561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
33661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
33761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
33861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item clicked listener on the fragment.
33961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * OnItemViewClickedListener will override {@link View.OnClickListener} that
34061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}.
34161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * So in general,  developer should choose one of the listeners but not both.
34261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
34361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
34461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemViewClickedListener = listener;
34561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
34661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.setOnItemViewClickedListener(listener);
34761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
34861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
34961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
35061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
35161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the item Clicked listener.
35261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
35361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewClickedListener getOnItemViewClickedListener() {
35461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemViewClickedListener;
35561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
35661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
35761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
358a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Starts a headers transition.
35961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
36061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>This method will begin a transition to either show or hide the
36161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * headers, depending on the value of withHeaders. If headers are disabled
36261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * for this browse fragment, this method will throw an exception.
36361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
36461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param withHeaders True if the headers should transition to being shown,
36561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        false if the transition should result in headers being hidden.
36661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
36761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void startHeadersTransition(boolean withHeaders) {
36861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (!mCanShowHeaders) {
36961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalStateException("Cannot start headers transition");
37061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
37161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (isInHeadersTransition() || mShowingHeaders == withHeaders) {
37261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
37361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
37461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        startHeadersTransitionInternal(withHeaders);
37561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
37661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
37761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
37861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if the headers transition is currently running.
37961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
38061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isInHeadersTransition() {
38161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersTransition != null;
38261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
38361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
38461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
38561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if headers are shown.
38661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
38761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isShowingHeaders() {
38861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mShowingHeaders;
38961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
39061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
392a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Sets a listener for browse fragment transitions.
39361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
39461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param listener The listener to call when a browse headers transition
39561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        begins or ends.
39661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
39761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBrowseTransitionListener(BrowseTransitionListener listener) {
39861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseTransitionListener = listener;
39961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
40061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
40161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
40261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Enables scaling of rows when headers are present.
40361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * By default enabled to increase density.
40461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
40561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param enable true to enable row scaling
40661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
40761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void enableRowScaling(boolean enable) {
40861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowScaleEnabled = enable;
40961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
41061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.enableRowScaling(mRowScaleEnabled);
41161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
41261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
41361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
41461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void startHeadersTransitionInternal(final boolean withHeaders) {
41561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getFragmentManager().isDestroyed()) {
41661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
41761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
41861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mShowingHeaders = withHeaders;
41961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.onExpandTransitionStart(!withHeaders, new Runnable() {
42061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
42161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
42261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.onTransitionStart();
42361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                createHeadersTransition();
42461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mBrowseTransitionListener != null) {
42561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
42661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
42761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                sTransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
42861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        mHeadersTransition);
42961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mHeadersBackStackEnabled) {
43061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (!withHeaders) {
43161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        getFragmentManager().beginTransaction()
43261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                                .addToBackStack(mWithHeadersBackStackName).commit();
43361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    } else {
43461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        int index = mBackStackChangedListener.mIndexOfHeadersBackStack;
43561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        if (index >= 0) {
43661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            BackStackEntry entry = getFragmentManager().getBackStackEntryAt(index);
43761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            getFragmentManager().popBackStackImmediate(entry.getId(),
43861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
43961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        }
44061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
44161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
44261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
44361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
44461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
44561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
44661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean isVerticalScrolling() {
44761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // don't run transition
44861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersSupportFragment.getVerticalGridView().getScrollState()
44961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                != HorizontalGridView.SCROLL_STATE_IDLE
45061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                || mRowsSupportFragment.getVerticalGridView().getScrollState()
45161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                != HorizontalGridView.SCROLL_STATE_IDLE;
45261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
45361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
454e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout
45561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
45661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new BrowseFrameLayout.OnFocusSearchListener() {
45761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
45861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public View onFocusSearch(View focused, int direction) {
45961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // if headers is running transition,  focus stays
4605ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout            if (mCanShowHeaders && isInHeadersTransition()) {
4615ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout                return focused;
4625ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout            }
46361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction);
4645ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout
465e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (getTitleView() != null && focused != getTitleView() &&
466e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                    direction == View.FOCUS_UP) {
467e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                return getTitleView();
468e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            }
469e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (getTitleView() != null && getTitleView().hasFocus() &&
470e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                    direction == View.FOCUS_DOWN) {
4715ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout                return mCanShowHeaders && mShowingHeaders ?
4725ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout                        mHeadersSupportFragment.getVerticalGridView() :
4735ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout                        mRowsSupportFragment.getVerticalGridView();
4745ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout            }
4755ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout
4768e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            boolean isRtl = ViewCompat.getLayoutDirection(focused) == View.LAYOUT_DIRECTION_RTL;
4778e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            int towardStart = isRtl ? View.FOCUS_RIGHT : View.FOCUS_LEFT;
4788e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            int towardEnd = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT;
479e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (mCanShowHeaders && direction == towardStart) {
48061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (isVerticalScrolling() || mShowingHeaders) {
48161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return focused;
48261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
48361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return mHeadersSupportFragment.getVerticalGridView();
4848e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing            } else if (direction == towardEnd) {
485e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                if (isVerticalScrolling()) {
48661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return focused;
48761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
48861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return mRowsSupportFragment.getVerticalGridView();
48961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
49061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return null;
49161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
49261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
49361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
49461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final BrowseFrameLayout.OnChildFocusListener mOnChildFocusListener =
49661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new BrowseFrameLayout.OnChildFocusListener() {
49761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
49961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
50028fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            if (getChildFragmentManager().isDestroyed()) {
50128fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu                return true;
50228fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            }
50361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // Make sure not changing focus when requestFocus() is called.
50461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mCanShowHeaders && mShowingHeaders) {
5057fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                if (mHeadersSupportFragment != null && mHeadersSupportFragment.getView() != null &&
5067fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                        mHeadersSupportFragment.getView().requestFocus(direction, previouslyFocusedRect)) {
50761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return true;
50861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
50961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
5107fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout            if (mRowsSupportFragment != null && mRowsSupportFragment.getView() != null &&
5117fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                    mRowsSupportFragment.getView().requestFocus(direction, previouslyFocusedRect)) {
51261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return true;
51361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
514e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            if (getTitleView() != null &&
515e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                    getTitleView().requestFocus(direction, previouslyFocusedRect)) {
5167fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout                return true;
5177fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout            }
5187fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout            return false;
51961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
52061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
52261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onRequestChildFocus(View child, View focused) {
52328fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            if (getChildFragmentManager().isDestroyed()) {
52428fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu                return;
52528fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            }
52661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (!mCanShowHeaders || isInHeadersTransition()) return;
52728fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            int childId = child.getId();
52861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (childId == R.id.browse_container_dock && mShowingHeaders) {
52961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(false);
53061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (childId == R.id.browse_headers_dock && !mShowingHeaders) {
53161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(true);
53261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
53361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
53461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
53561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
53661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
53761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onSaveInstanceState(Bundle outState) {
538e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        super.onSaveInstanceState(outState);
53961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBackStackChangedListener != null) {
54061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mBackStackChangedListener.save(outState);
54161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
54261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            outState.putBoolean(HEADER_SHOW, mShowingHeaders);
54361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
54461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
54561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
54661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
54761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onCreate(Bundle savedInstanceState) {
54861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onCreate(savedInstanceState);
54961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        TypedArray ta = getActivity().obtainStyledAttributes(R.styleable.LeanbackTheme);
5508e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        mContainerListMarginStart = (int) ta.getDimension(
55146443cb5b092f1d9156342645088eead9da026f6Dake Gu                R.styleable.LeanbackTheme_browseRowsMarginStart, getActivity().getResources()
55246443cb5b092f1d9156342645088eead9da026f6Dake Gu                .getDimensionPixelSize(R.dimen.lb_browse_rows_margin_start));
55361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mContainerListAlignTop = (int) ta.getDimension(
55446443cb5b092f1d9156342645088eead9da026f6Dake Gu                R.styleable.LeanbackTheme_browseRowsMarginTop, getActivity().getResources()
55546443cb5b092f1d9156342645088eead9da026f6Dake Gu                .getDimensionPixelSize(R.dimen.lb_browse_rows_margin_top));
55661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ta.recycle();
55761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
55861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        readArguments(getArguments());
55961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
56034f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout        if (mCanShowHeaders) {
56134f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            if (mHeadersBackStackEnabled) {
56234f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mWithHeadersBackStackName = LB_HEADERS_BACKSTACK + this;
56334f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mBackStackChangedListener = new BackStackListener();
56434f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                getFragmentManager().addOnBackStackChangedListener(mBackStackChangedListener);
56534f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mBackStackChangedListener.load(savedInstanceState);
56634f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            } else {
56734f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                if (savedInstanceState != null) {
56834f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                    mShowingHeaders = savedInstanceState.getBoolean(HEADER_SHOW);
56934f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                }
57034f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            }
57134f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout        }
57261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
57361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
57461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
57561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onDestroy() {
57661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBackStackChangedListener != null) {
57761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getFragmentManager().removeOnBackStackChangedListener(mBackStackChangedListener);
57861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
57961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onDestroy();
58061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
58161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
58261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
58361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public View onCreateView(LayoutInflater inflater, ViewGroup container,
58461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            Bundle savedInstanceState) {
58561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getChildFragmentManager().findFragmentById(R.id.browse_container_dock) == null) {
58661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment = new RowsSupportFragment();
58761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment = new HeadersSupportFragment();
58861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getChildFragmentManager().beginTransaction()
58961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .replace(R.id.browse_headers_dock, mHeadersSupportFragment)
59061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .replace(R.id.browse_container_dock, mRowsSupportFragment).commit();
59161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
59261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment = (HeadersSupportFragment) getChildFragmentManager()
59361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .findFragmentById(R.id.browse_headers_dock);
59461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment = (RowsSupportFragment) getChildFragmentManager()
59561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .findFragmentById(R.id.browse_container_dock);
59661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
59761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
59861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders);
59961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
60061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setAdapter(mAdapter);
60161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeaderPresenterSelector != null) {
60261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector);
60361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
60461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setAdapter(mAdapter);
60561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
60661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.enableRowScaling(mRowScaleEnabled);
60761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setOnItemViewSelectedListener(mRowViewSelectedListener);
6088df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu        mHeadersSupportFragment.setOnHeaderViewSelectedListener(mHeaderViewSelectedListener);
60961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setOnHeaderClickedListener(mHeaderClickedListener);
61061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setOnItemViewClickedListener(mOnItemViewClickedListener);
61161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
61261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        View root = inflater.inflate(R.layout.lb_browse_fragment, container, false);
61361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
614e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        setTitleView((TitleView) root.findViewById(R.id.browse_title_group));
615e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout
61661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame);
61761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame.setOnChildFocusListener(mOnChildFocusListener);
618e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener);
61961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
62061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBrandColorSet) {
62161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setBackgroundColor(mBrandColor);
62261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
62361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
62461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
62561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
62661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
62761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                showHeaders(true);
62861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
62961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
63061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSceneWithoutHeaders =  sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
63161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
63261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
63361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                showHeaders(false);
63461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
63561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
636c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mSceneAfterEntranceTransition = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
637c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            @Override
638c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            public void run() {
639c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                setEntranceTransitionEndState();
640c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
641c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        });
64261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return root;
64361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
64461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
64561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void createHeadersTransition() {
6464735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu        mHeadersTransition = sTransitionHelper.loadTransition(getActivity(),
6474735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu                mShowingHeaders ?
6484735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu                R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out);
64961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
65061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setTransitionListener(mHeadersTransition, new TransitionListener() {
65161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
65261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onTransitionStart(Object transition) {
65361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
65461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
65561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onTransitionEnd(Object transition) {
65661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersTransition = null;
65761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mRowsSupportFragment.onTransitionEnd();
65861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.onTransitionEnd();
65961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mShowingHeaders) {
66061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    VerticalGridView headerGridView = mHeadersSupportFragment.getVerticalGridView();
66161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (headerGridView != null && !headerGridView.hasFocus()) {
66261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        headerGridView.requestFocus();
66361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
66461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                } else {
66561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    VerticalGridView rowsGridView = mRowsSupportFragment.getVerticalGridView();
66661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (rowsGridView != null && !rowsGridView.hasFocus()) {
66761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        rowsGridView.requestFocus();
66861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
66961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
67061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mBrowseTransitionListener != null) {
67161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mBrowseTransitionListener.onHeadersTransitionStop(mShowingHeaders);
67261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
67361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
67461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
67561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
67661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
67761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
67861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the {@link PresenterSelector} used to render the row headers.
67961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
68061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headerPresenterSelector The PresenterSelector that will determine
68161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        the Presenter for each row header.
68261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
68361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setHeaderPresenterSelector(PresenterSelector headerPresenterSelector) {
68461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeaderPresenterSelector = headerPresenterSelector;
68561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeadersSupportFragment != null) {
68661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector);
68761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
68861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
68961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
690c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void setRowsAlignedLeft(boolean alignLeft) {
69161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        MarginLayoutParams lp;
69261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        View containerList;
69361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList = mRowsSupportFragment.getView();
69461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        lp = (MarginLayoutParams) containerList.getLayoutParams();
6958e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        lp.setMarginStart(alignLeft ? 0 : mContainerListMarginStart);
69661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList.setLayoutParams(lp);
697c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
69861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
699c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void setHeadersOnScreen(boolean onScreen) {
700c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        MarginLayoutParams lp;
701c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        View containerList;
70261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList = mHeadersSupportFragment.getView();
70361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        lp = (MarginLayoutParams) containerList.getLayoutParams();
7048e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        lp.setMarginStart(onScreen ? 0 : -mContainerListMarginStart);
70561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList.setLayoutParams(lp);
706c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
70761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
708c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void showHeaders(boolean show) {
709c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (DEBUG) Log.v(TAG, "showHeaders " + show);
710c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mHeadersSupportFragment.setHeadersEnabled(show);
711c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(show);
712c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setRowsAlignedLeft(!show);
71361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setExpand(!show);
71461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
71561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
71661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private HeadersSupportFragment.OnHeaderClickedListener mHeaderClickedListener =
71761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        new HeadersSupportFragment.OnHeaderClickedListener() {
71861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
71961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onHeaderClicked() {
72061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mCanShowHeaders || !mShowingHeaders || isInHeadersTransition()) {
72161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return;
72261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
72361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(false);
72461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mRowsSupportFragment.getVerticalGridView().requestFocus();
72561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
72661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
72761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
72861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mRowViewSelectedListener = new OnItemViewSelectedListener() {
72961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
73061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
73161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                RowPresenter.ViewHolder rowViewHolder, Row row) {
73261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int position = mRowsSupportFragment.getVerticalGridView().getSelectedPosition();
73361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "row selected position " + position);
73461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            onRowSelected(position);
73561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalOnItemViewSelectedListener != null) {
73661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
73761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        rowViewHolder, row);
73861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
73961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
74061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
74161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7428df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu    private HeadersSupportFragment.OnHeaderViewSelectedListener mHeaderViewSelectedListener =
7438df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu            new HeadersSupportFragment.OnHeaderViewSelectedListener() {
74461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
7458df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu        public void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
74661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int position = mHeadersSupportFragment.getVerticalGridView().getSelectedPosition();
74761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "header selected position " + position);
74861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            onRowSelected(position);
74961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
75061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
75161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
75261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void onRowSelected(int position) {
75361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (position != mSelectedPosition) {
754aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout            mSetSelectionRunnable.post(
755aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                    position, SetSelectionRunnable.TYPE_INTERNAL_SYNC, true);
75661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
75761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (getAdapter() == null || getAdapter().size() == 0 || position == 0) {
758e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                showTitle(true);
759e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout            } else {
760e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout                showTitle(false);
76161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
76261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
76361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
76461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7653f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    private void setSelection(int position, boolean smooth) {
76661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (position != NO_POSITION) {
7673f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu            mRowsSupportFragment.setSelectedPosition(position, smooth);
7683f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu            mHeadersSupportFragment.setSelectedPosition(position, smooth);
76961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
77061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSelectedPosition = position;
77161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
77261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7733f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    /**
7743f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     * Sets the selected row position with smooth animation.
7753f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     */
7763f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    public void setSelectedPosition(int position) {
7773f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        setSelectedPosition(position, true);
7783f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    }
7793f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu
7803f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    /**
7813f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     * Sets the selected row position.
7823f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu     */
7833f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    public void setSelectedPosition(int position, boolean smooth) {
784aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout        mSetSelectionRunnable.post(
785aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout                position, SetSelectionRunnable.TYPE_USER_REQUEST, smooth);
7863f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    }
7873f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu
78861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
78961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onStart() {
79061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onStart();
79161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setWindowAlignmentFromTop(mContainerListAlignTop);
79261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setItemAlignment();
79361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setWindowAlignmentFromTop(mContainerListAlignTop);
79461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setItemAlignment();
79561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7963595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        mRowsSupportFragment.setScalePivots(0, mContainerListAlignTop);
79761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
79861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mCanShowHeaders && mShowingHeaders && mHeadersSupportFragment.getView() != null) {
79961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.getView().requestFocus();
80061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else if ((!mCanShowHeaders || !mShowingHeaders)
80161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                && mRowsSupportFragment.getView() != null) {
80261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.getView().requestFocus();
80361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
80461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mCanShowHeaders) {
80561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            showHeaders(mShowingHeaders);
80661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
8073f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        if (isEntranceTransitionEnabled()) {
808c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            setEntranceTransitionStartState();
809c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
81061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
81161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
81261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
813a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Enables/disables headers transition on back key support. This is enabled by
81461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * default. The BrowseSupportFragment will add a back stack entry when headers are
81561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * showing. Running a headers transition when the back key is pressed only
81661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * works when the headers state is {@link #HEADERS_ENABLED} or
81761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link #HEADERS_HIDDEN}.
81861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>
81961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * NOTE: If an Activity has its own onBackPressed() handling, you must
82061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * disable this feature. You may use {@link #startHeadersTransition(boolean)}
82161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * and {@link BrowseTransitionListener} in your own back stack handling.
82261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
82361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public final void setHeadersTransitionOnBackEnabled(boolean headersBackStackEnabled) {
82461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersBackStackEnabled = headersBackStackEnabled;
82561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
82661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
82761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
82861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if headers transition on back key support is enabled.
82961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
83061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public final boolean isHeadersTransitionOnBackEnabled() {
83161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersBackStackEnabled;
83261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
83361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
83461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void readArguments(Bundle args) {
83561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args == null) {
83661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
83761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
83861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args.containsKey(ARG_TITLE)) {
83961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setTitle(args.getString(ARG_TITLE));
84061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
84161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args.containsKey(ARG_HEADERS_STATE)) {
84261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setHeadersState(args.getInt(ARG_HEADERS_STATE));
84361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
84461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
84561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
84661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
84761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the state for the headers column in the browse fragment. Must be one
84861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * of {@link #HEADERS_ENABLED}, {@link #HEADERS_HIDDEN}, or
84961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link #HEADERS_DISABLED}.
85061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
85161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headersState The state of the headers for the browse fragment.
85261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
85361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setHeadersState(int headersState) {
85461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (headersState < HEADERS_ENABLED || headersState > HEADERS_DISABLED) {
85561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalArgumentException("Invalid headers state: " + headersState);
85661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
85761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "setHeadersState " + headersState);
85861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
85961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (headersState != mHeadersState) {
86061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersState = headersState;
86161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            switch (headersState) {
86261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_ENABLED:
86361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = true;
86461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = true;
86561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
86661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_HIDDEN:
86761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = true;
86861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = false;
86961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
87061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_DISABLED:
87161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = false;
87261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = false;
87361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
87461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                default:
87561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    Log.w(TAG, "Unknown headers state: " + headersState);
87661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
87761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
87861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mHeadersSupportFragment != null) {
87961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders);
88061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
88161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
88261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
88361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
88461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
88561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the state of the headers column in the browse fragment.
88661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
88761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getHeadersState() {
88861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersState;
88961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
890c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
8913f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
8923f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected Object createEntranceTransition() {
8933f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        return sTransitionHelper.loadTransition(getActivity(),
8943f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu                R.transition.lb_browse_entrance_transition);
895c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
896c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
8973f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
8983f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected void runEntranceTransition(Object entranceTransition) {
8993f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
9003f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu                entranceTransition);
901c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
902c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
9033f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
9043f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected void onEntranceTransitionStart() {
9053f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mHeadersSupportFragment.onTransitionStart();
9063f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mRowsSupportFragment.onTransitionStart();
907c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
908c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
9093f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    @Override
9103f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    protected void onEntranceTransitionEnd() {
9113f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mRowsSupportFragment.onTransitionEnd();
9123f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mHeadersSupportFragment.onTransitionEnd();
913c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
914c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
9153f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    void setSearchOrbViewOnScreen(boolean onScreen) {
916e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout        View searchOrbView = getTitleView().getSearchAffordanceView();
917c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        MarginLayoutParams lp = (MarginLayoutParams) searchOrbView.getLayoutParams();
9188e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing        lp.setMarginStart(onScreen ? 0 : -mContainerListMarginStart);
919c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        searchOrbView.setLayoutParams(lp);
920c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
921c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
922c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void setEntranceTransitionStartState() {
923c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(false);
924c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setSearchOrbViewOnScreen(false);
9253f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mRowsSupportFragment.setEntranceTransitionState(false);
926c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
927c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
928c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void setEntranceTransitionEndState() {
929c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(mShowingHeaders);
930c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setSearchOrbViewOnScreen(true);
9313f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        mRowsSupportFragment.setEntranceTransitionState(true);
932c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
933c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
93461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu}
93561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
936