BrowseSupportFragment.java revision 3595aa0cbdaa8e754365ca94a0b9eb8fc52b9796
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;
1961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionHelper;
2061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionListener;
2161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.BrowseFrameLayout;
2261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.HorizontalGridView;
2361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ItemBridgeAdapter;
2461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewClickedListener;
2561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewSelectedListener;
2661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Presenter;
2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.PresenterSelector;
2861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter;
2961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.TitleView;
3061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
3161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Row;
3261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ObjectAdapter;
3361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemSelectedListener;
3461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemClickedListener;
3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.SearchOrbView;
3661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log;
3761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.FragmentActivity;
3861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.Fragment;
3961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.FragmentManager;
4061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v4.app.FragmentManager.BackStackEntry;
4161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.content.Context;
4261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.content.res.TypedArray;
4361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Bundle;
4461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.LayoutInflater;
4561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View;
4661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View.OnClickListener;
4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup;
4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup.MarginLayoutParams;
49c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Guimport android.view.ViewTreeObserver;
5061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.Color;
5161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.Rect;
5261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.drawable.Drawable;
5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
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)}.
7361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
7461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupublic class BrowseSupportFragment extends Fragment {
7561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for saving header show/hide status when backstack is used:
7761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String HEADER_STACK_INDEX = "headerStackIndex";
7861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for saving header show/hide status when backstack is not used:
7961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String HEADER_SHOW = "headerShow";
8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // BUNDLE attribute for title is showing
8161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static final String TITLE_SHOW = "titleShow";
8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    final class BackStackListener implements FragmentManager.OnBackStackChangedListener {
8461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mLastEntryCount;
8561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mIndexOfHeadersBackStack;
8661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
8761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        BackStackListener() {
8861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLastEntryCount = getFragmentManager().getBackStackEntryCount();
8961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mIndexOfHeadersBackStack = -1;
9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void load(Bundle savedInstanceState) {
9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (savedInstanceState != null) {
9461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mIndexOfHeadersBackStack = savedInstanceState.getInt(HEADER_STACK_INDEX, -1);
9561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mShowingHeaders = mIndexOfHeadersBackStack == -1;
9661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
9761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mShowingHeaders) {
9861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    getFragmentManager().beginTransaction()
9961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            .addToBackStack(mWithHeadersBackStackName).commit();
10061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
10161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
10261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        void save(Bundle outState) {
10561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            outState.putInt(HEADER_STACK_INDEX, mIndexOfHeadersBackStack);
10661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onBackStackChanged() {
11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (getFragmentManager() == null) {
11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                Log.w(TAG, "getFragmentManager() is null, stack:", new Exception());
11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return;
11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int count = getFragmentManager().getBackStackEntryCount();
11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // if backstack is growing and last pushed entry is "headers" backstack,
11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // remember the index of the entry.
11861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (count > mLastEntryCount) {
11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                BackStackEntry entry = getFragmentManager().getBackStackEntryAt(count - 1);
12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mWithHeadersBackStackName.equals(entry.getName())) {
12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mIndexOfHeadersBackStack = count - 1;
12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (count < mLastEntryCount) {
12461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                // if popped "headers" backstack, initiate the show header transition if needed
12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mIndexOfHeadersBackStack >= count) {
12661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mIndexOfHeadersBackStack = -1;
12761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (!mShowingHeaders) {
12861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        startHeadersTransitionInternal(true);
12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLastEntryCount = count;
13361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
13461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
13561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
13661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
13761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Listener for transitions between browse headers and rows.
13861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
13961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static class BrowseTransitionListener {
14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        /**
14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * Callback when headers transition starts.
14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *
14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * @param withHeaders True if the transition will result in headers
14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *        being shown, false otherwise.
14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         */
14661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onHeadersTransitionStart(boolean withHeaders) {
14761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
14861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        /**
14961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * Callback when headers transition stops.
15061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *
15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         * @param withHeaders True if the transition will result in headers
15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         *        being shown, false otherwise.
15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu         */
15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onHeadersTransitionStop(boolean withHeaders) {
15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
15761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
15861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String TAG = "BrowseSupportFragment";
15961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
16061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String LB_HEADERS_BACKSTACK = "lbHeadersBackStack_";
16161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
16261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static boolean DEBUG = false;
16361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
16461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is enabled and shown by default. */
16561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_ENABLED = 1;
16661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
16761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is enabled and hidden by default. */
16861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_HIDDEN = 2;
16961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
17061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /** The headers fragment is disabled and will never be shown. */
17161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int HEADERS_DISABLED = 3;
17261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
17361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final float SLIDE_DISTANCE_FACTOR = 2;
17461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
17561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private RowsSupportFragment mRowsSupportFragment;
17661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private HeadersSupportFragment mHeadersSupportFragment;
17761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
17861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ObjectAdapter mAdapter;
17961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
18061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private String mTitle;
18161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Drawable mBadgeDrawable;
18261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mHeadersState = HEADERS_ENABLED;
18361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBrandColor = Color.TRANSPARENT;
18461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mBrandColorSet;
18561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
18661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BrowseFrameLayout mBrowseFrame;
18761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private TitleView mTitleView;
18861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mShowingTitle = true;
18961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mHeadersBackStackEnabled = true;
19061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private String mWithHeadersBackStackName;
19161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mShowingHeaders = true;
19261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mCanShowHeaders = true;
19361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mContainerListMarginLeft;
19461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mContainerListAlignTop;
19561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mRowScaleEnabled = true;
19661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private SearchOrbView.Colors mSearchAffordanceColors;
19761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mSearchAffordanceColorSet;
19861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemSelectedListener mExternalOnItemSelectedListener;
19961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnClickListener mExternalOnSearchClickedListener;
20061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemClickedListener mOnItemClickedListener;
20161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mExternalOnItemViewSelectedListener;
20261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewClickedListener mOnItemViewClickedListener;
20361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mSelectedPosition = -1;
20461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
20561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private PresenterSelector mHeaderPresenterSelector;
20661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
20761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // transition related:
20861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
20961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mReparentHeaderId = View.generateViewId();
21061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithTitle;
21161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithoutTitle;
21261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithHeaders;
21361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mSceneWithoutHeaders;
214c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private Object mSceneAfterEntranceTransition;
21561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mTitleUpTransition;
21661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mTitleDownTransition;
21761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private Object mHeadersTransition;
218c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private Object mEntranceTransition;
21961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mHeadersTransitionStartDelay;
22061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mHeadersTransitionDuration;
22161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BackStackListener mBackStackChangedListener;
22261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private BrowseTransitionListener mBrowseTransitionListener;
22361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
224c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private boolean mEntranceTransitionEnabled = false;
225c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private boolean mStartEntranceTransitionPending = false;
226c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
22761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_TITLE = BrowseSupportFragment.class.getCanonicalName() + ".title";
22861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_BADGE_URI = BrowseSupportFragment.class.getCanonicalName() + ".badge";
22961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String ARG_HEADERS_STATE =
23061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        BrowseSupportFragment.class.getCanonicalName() + ".headersState";
23161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
23261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
23361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Create arguments for a browse fragment.
23461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
23561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param args The Bundle to place arguments into, or null if the method
23661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        should return a new Bundle.
23761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param title The title of the BrowseSupportFragment.
23861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headersState The initial state of the headers of the
23961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        BrowseSupportFragment. Must be one of {@link #HEADERS_ENABLED}, {@link
24061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        #HEADERS_HIDDEN}, or {@link #HEADERS_DISABLED}.
24161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @return A Bundle with the given arguments for creating a BrowseSupportFragment.
24261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
24361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static Bundle createArgs(Bundle args, String title, int headersState) {
24461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args == null) {
24561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            args = new Bundle();
24661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
24761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        args.putString(ARG_TITLE, title);
24861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        args.putInt(ARG_HEADERS_STATE, headersState);
24961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return args;
25061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
25161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
25261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
25361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the brand color for the browse fragment. The brand color is used as
25461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the primary color for UI elements in the browse fragment. For example,
25561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the background color of the headers fragment uses the brand color.
25661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
25761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param color The color to use as the brand color of the fragment.
25861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
25961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBrandColor(int color) {
26061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrandColor = color;
26161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrandColorSet = true;
26261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
26361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeadersSupportFragment != null) {
26461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setBackgroundColor(mBrandColor);
26561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
26661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
26761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
26861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
26961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the brand color for the browse fragment.
27061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * The default is transparent.
27161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
27261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getBrandColor() {
27361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mBrandColor;
27461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
27561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
27661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
27761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the adapter containing the rows for the fragment.
27861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
27961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>The items referenced by the adapter must be be derived from
28061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link Row}. These rows will be used by the rows fragment and the headers
28161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * fragment (if not disabled) to render the browse rows.
28261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
28361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param adapter An ObjectAdapter for the browse rows. All items must
28461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        derive from {@link Row}.
28561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
28661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setAdapter(ObjectAdapter adapter) {
28761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mAdapter = adapter;
28861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
28961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.setAdapter(adapter);
29061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setAdapter(adapter);
29161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
29261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
29361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
29461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
29561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the adapter containing the rows for the fragment.
29661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
29761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public ObjectAdapter getAdapter() {
29861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mAdapter;
29961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
30061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
30161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
30261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item selection listener. This listener will be called when an
30361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * item or row is selected by a user.
30461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
30561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param listener The listener to call when an item or row is selected.
30661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @deprecated Use {@link #setOnItemViewSelectedListener(OnItemViewSelectedListener)}
30761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
30861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
30961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExternalOnItemSelectedListener = listener;
31061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
31161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
31261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
31361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item selection listener.
31461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
31561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
31661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExternalOnItemViewSelectedListener = listener;
31761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
31861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
31961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
32061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns an item selection listener.
32161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
32261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewSelectedListener getOnItemViewSelectedListener() {
32361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mExternalOnItemViewSelectedListener;
32461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
32561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
32661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
32761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item clicked listener on the fragment.
32861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
32961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>OnItemClickedListener will override {@link View.OnClickListener} that
33061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * an item presenter may set during
33161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link Presenter#onCreateViewHolder(ViewGroup)}. So in general, you
33261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * should choose to use an {@link OnItemClickedListener} or a
33361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link View.OnClickListener} on your item views, but not both.
33461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
33561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param listener The listener to call when an item is clicked.
33661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @deprecated Use {@link #setOnItemViewClickedListener(OnItemViewClickedListener)}
33761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
33861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemClickedListener(OnItemClickedListener listener) {
33961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemClickedListener = listener;
34061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
34161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.setOnItemClickedListener(listener);
34261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
34361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
34461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
34561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
34661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the item clicked listener.
34761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @deprecated Use {@link #getOnItemViewClickedListener()}
34861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
34961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemClickedListener getOnItemClickedListener() {
35061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemClickedListener;
35161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
35261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
35361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
35461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets an item clicked listener on the fragment.
35561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * OnItemViewClickedListener will override {@link View.OnClickListener} that
35661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}.
35761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * So in general,  developer should choose one of the listeners but not both.
35861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
35961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
36061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOnItemViewClickedListener = listener;
36161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
36261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.setOnItemViewClickedListener(listener);
36361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
36461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
36561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
36661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
36761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the item Clicked listener.
36861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
36961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnItemViewClickedListener getOnItemViewClickedListener() {
37061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mOnItemViewClickedListener;
37161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
37261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
37361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
37461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets a click listener for the search affordance.
37561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
37661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>The presence of a listener will change the visibility of the search
37761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * affordance in the fragment title. When set to non-null, the title will
37861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * contain an element that a user may click to begin a search.
37961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
38061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>The listener's {@link View.OnClickListener#onClick onClick} method
38161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * will be invoked when the user clicks on the search element.
38261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
38361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param listener The listener to call when the search element is clicked.
38461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
38561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setOnSearchClickedListener(View.OnClickListener listener) {
38661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mExternalOnSearchClickedListener = listener;
38761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mTitleView != null) {
38861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mTitleView.setOnSearchClickedListener(listener);
38961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
39061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
39161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
39361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the {@link SearchOrbView.Colors} used to draw the search affordance.
39461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
39561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setSearchAffordanceColors(SearchOrbView.Colors colors) {
39661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSearchAffordanceColors = colors;
39761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSearchAffordanceColorSet = true;
39861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mTitleView != null) {
39961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mTitleView.setSearchAffordanceColors(mSearchAffordanceColors);
40061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
40161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
40261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
40361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
40461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the {@link SearchOrbView.Colors} used to draw the search affordance.
40561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
40661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public SearchOrbView.Colors getSearchAffordanceColors() {
40761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mSearchAffordanceColorSet) {
40861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return mSearchAffordanceColors;
40961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
41061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mTitleView == null) {
41161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalStateException("Fragment views not yet created");
41261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
41361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mTitleView.getSearchAffordanceColors();
41461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
41561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
41661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
41761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the color used to draw the search affordance.
41861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * A default brighter color will be set by the framework.
41961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
42061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param color The color to use for the search affordance.
42161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
42261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setSearchAffordanceColor(int color) {
42361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        setSearchAffordanceColors(new SearchOrbView.Colors(color));
42461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
42561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
42661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
42761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the color used to draw the search affordance.
42861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
42961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getSearchAffordanceColor() {
43061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return getSearchAffordanceColors().color;
43161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
43261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
43361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
43461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Start a headers transition.
43561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
43661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>This method will begin a transition to either show or hide the
43761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * headers, depending on the value of withHeaders. If headers are disabled
43861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * for this browse fragment, this method will throw an exception.
43961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
44061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param withHeaders True if the headers should transition to being shown,
44161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        false if the transition should result in headers being hidden.
44261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
44361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void startHeadersTransition(boolean withHeaders) {
44461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (!mCanShowHeaders) {
44561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalStateException("Cannot start headers transition");
44661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
44761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (isInHeadersTransition() || mShowingHeaders == withHeaders) {
44861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
44961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
45061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        startHeadersTransitionInternal(withHeaders);
45161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
45261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
45361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
45461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if the headers transition is currently running.
45561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
45661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isInHeadersTransition() {
45761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersTransition != null;
45861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
45961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
46061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
46161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if headers are shown.
46261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
46361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isShowingHeaders() {
46461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mShowingHeaders;
46561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
46661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
46761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
46861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Set a listener for browse fragment transitions.
46961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
47061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param listener The listener to call when a browse headers transition
47161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        begins or ends.
47261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
47361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBrowseTransitionListener(BrowseTransitionListener listener) {
47461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseTransitionListener = listener;
47561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
47661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
47761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
47861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Enables scaling of rows when headers are present.
47961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * By default enabled to increase density.
48061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
48161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param enable true to enable row scaling
48261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
48361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void enableRowScaling(boolean enable) {
48461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowScaleEnabled = enable;
48561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRowsSupportFragment != null) {
48661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.enableRowScaling(mRowScaleEnabled);
48761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
48861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
48961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void startHeadersTransitionInternal(final boolean withHeaders) {
49161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getFragmentManager().isDestroyed()) {
49261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
49361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
49461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mShowingHeaders = withHeaders;
49561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.onExpandTransitionStart(!withHeaders, new Runnable() {
49661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
49761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
49861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.onTransitionStart();
49961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                createHeadersTransition();
50061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mBrowseTransitionListener != null) {
50161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mBrowseTransitionListener.onHeadersTransitionStart(withHeaders);
50261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
50361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                sTransitionHelper.runTransition(withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders,
50461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        mHeadersTransition);
50561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mHeadersBackStackEnabled) {
50661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (!withHeaders) {
50761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        getFragmentManager().beginTransaction()
50861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                                .addToBackStack(mWithHeadersBackStackName).commit();
50961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    } else {
51061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        int index = mBackStackChangedListener.mIndexOfHeadersBackStack;
51161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        if (index >= 0) {
51261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            BackStackEntry entry = getFragmentManager().getBackStackEntryAt(index);
51361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            getFragmentManager().popBackStackImmediate(entry.getId(),
51461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
51561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        }
51661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
51761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
51861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
51961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
52061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
52161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean isVerticalScrolling() {
52361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // don't run transition
52461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersSupportFragment.getVerticalGridView().getScrollState()
52561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                != HorizontalGridView.SCROLL_STATE_IDLE
52661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                || mRowsSupportFragment.getVerticalGridView().getScrollState()
52761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                != HorizontalGridView.SCROLL_STATE_IDLE;
52861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
52961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
53061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
53161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new BrowseFrameLayout.OnFocusSearchListener() {
53261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
53361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public View onFocusSearch(View focused, int direction) {
53461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // If headers fragment is disabled, just return null.
53561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (!mCanShowHeaders) return null;
53661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
53761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final View searchOrbView = mTitleView.getSearchAffordanceView();
53861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // if headers is running transition,  focus stays
53961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (isInHeadersTransition()) return focused;
54061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction);
54161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (direction == View.FOCUS_LEFT) {
54261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (isVerticalScrolling() || mShowingHeaders) {
54361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return focused;
54461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
54561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return mHeadersSupportFragment.getVerticalGridView();
54661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (direction == View.FOCUS_RIGHT) {
54761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (isVerticalScrolling() || !mShowingHeaders) {
54861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return focused;
54961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
55061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return mRowsSupportFragment.getVerticalGridView();
55161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (focused == searchOrbView && direction == View.FOCUS_DOWN) {
55261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return mShowingHeaders ? mHeadersSupportFragment.getVerticalGridView() :
55361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mRowsSupportFragment.getVerticalGridView();
55461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
55561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (focused != searchOrbView && searchOrbView.getVisibility() == View.VISIBLE
55661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    && direction == View.FOCUS_UP) {
55761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return searchOrbView;
55861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
55961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
56061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return null;
56161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
56261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
56361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
56461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
56561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final BrowseFrameLayout.OnChildFocusListener mOnChildFocusListener =
56661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new BrowseFrameLayout.OnChildFocusListener() {
56761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
56861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
56961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
57028fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            if (getChildFragmentManager().isDestroyed()) {
57128fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu                return true;
57228fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            }
57361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // Make sure not changing focus when requestFocus() is called.
57461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mCanShowHeaders && mShowingHeaders) {
57561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mHeadersSupportFragment.getView().requestFocus(direction, previouslyFocusedRect)) {
57661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return true;
57761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
57861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
57961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mRowsSupportFragment.getView().requestFocus(direction, previouslyFocusedRect)) {
58061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                return true;
58161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
58261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return mTitleView.requestFocus(direction, previouslyFocusedRect);
58361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
58461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
58561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
58661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onRequestChildFocus(View child, View focused) {
58728fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            if (getChildFragmentManager().isDestroyed()) {
58828fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu                return;
58928fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            }
59061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (!mCanShowHeaders || isInHeadersTransition()) return;
59128fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu            int childId = child.getId();
59261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (childId == R.id.browse_container_dock && mShowingHeaders) {
59361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(false);
59461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (childId == R.id.browse_headers_dock && !mShowingHeaders) {
59561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(true);
59661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
59761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
59861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
59961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
60061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
60161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onSaveInstanceState(Bundle outState) {
60261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBackStackChangedListener != null) {
60361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mBackStackChangedListener.save(outState);
60461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
60561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            outState.putBoolean(HEADER_SHOW, mShowingHeaders);
60661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
60761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        outState.putBoolean(TITLE_SHOW, mShowingTitle);
60861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
60961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
61061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
61161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onCreate(Bundle savedInstanceState) {
61261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onCreate(savedInstanceState);
61361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        TypedArray ta = getActivity().obtainStyledAttributes(R.styleable.LeanbackTheme);
61461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mContainerListMarginLeft = (int) ta.getDimension(
61561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                R.styleable.LeanbackTheme_browseRowsMarginStart, 0);
61661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mContainerListAlignTop = (int) ta.getDimension(
61761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                R.styleable.LeanbackTheme_browseRowsMarginTop, 0);
61861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ta.recycle();
61961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
62061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersTransitionStartDelay = getResources()
62161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                .getInteger(R.integer.lb_browse_headers_transition_delay);
62261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersTransitionDuration = getResources()
62361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                .getInteger(R.integer.lb_browse_headers_transition_duration);
62461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
62561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        readArguments(getArguments());
62661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
62734f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout        if (mCanShowHeaders) {
62834f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            if (mHeadersBackStackEnabled) {
62934f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mWithHeadersBackStackName = LB_HEADERS_BACKSTACK + this;
63034f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mBackStackChangedListener = new BackStackListener();
63134f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                getFragmentManager().addOnBackStackChangedListener(mBackStackChangedListener);
63234f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                mBackStackChangedListener.load(savedInstanceState);
63334f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            } else {
63434f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                if (savedInstanceState != null) {
63534f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                    mShowingHeaders = savedInstanceState.getBoolean(HEADER_SHOW);
63634f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout                }
63734f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout            }
63834f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout        }
63934f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout
64061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
64161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
64261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
64361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onDestroy() {
64461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBackStackChangedListener != null) {
64561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getFragmentManager().removeOnBackStackChangedListener(mBackStackChangedListener);
64661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
64761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onDestroy();
64861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
64961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
65061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
65161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public View onCreateView(LayoutInflater inflater, ViewGroup container,
65261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            Bundle savedInstanceState) {
65361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getChildFragmentManager().findFragmentById(R.id.browse_container_dock) == null) {
65461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment = new RowsSupportFragment();
65561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment = new HeadersSupportFragment();
65661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getChildFragmentManager().beginTransaction()
65761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .replace(R.id.browse_headers_dock, mHeadersSupportFragment)
65861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .replace(R.id.browse_container_dock, mRowsSupportFragment).commit();
65961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
66061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment = (HeadersSupportFragment) getChildFragmentManager()
66161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .findFragmentById(R.id.browse_headers_dock);
66261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment = (RowsSupportFragment) getChildFragmentManager()
66361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    .findFragmentById(R.id.browse_container_dock);
66461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
66561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
66661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders);
66761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
66861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setAdapter(mAdapter);
66961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeaderPresenterSelector != null) {
67061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector);
67161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
67261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setAdapter(mAdapter);
67361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
67461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.enableRowScaling(mRowScaleEnabled);
67561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setOnItemSelectedListener(mRowSelectedListener);
67661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setOnItemViewSelectedListener(mRowViewSelectedListener);
67761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setOnItemSelectedListener(mHeaderSelectedListener);
67861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setOnHeaderClickedListener(mHeaderClickedListener);
67961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setOnItemClickedListener(mOnItemClickedListener);
68061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setOnItemViewClickedListener(mOnItemViewClickedListener);
68161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
68261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        View root = inflater.inflate(R.layout.lb_browse_fragment, container, false);
68361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
68461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame);
68561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener);
68661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBrowseFrame.setOnChildFocusListener(mOnChildFocusListener);
68761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
68861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitleView = (TitleView) root.findViewById(R.id.browse_title_group);
68961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitleView.setTitle(mTitle);
69061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitleView.setBadgeDrawable(mBadgeDrawable);
69161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mSearchAffordanceColorSet) {
69261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mTitleView.setSearchAffordanceColors(mSearchAffordanceColors);
69361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
69461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mExternalOnSearchClickedListener != null) {
69561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mTitleView.setOnSearchClickedListener(mExternalOnSearchClickedListener);
69661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
69761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
69861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBrandColorSet) {
69961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setBackgroundColor(mBrandColor);
70061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
70161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
70261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSceneWithTitle = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
70361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
70461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
70561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mTitleView.setVisibility(View.VISIBLE);
70661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
70761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
70861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSceneWithoutTitle = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
70961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
71061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
71161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mTitleView.setVisibility(View.INVISIBLE);
71261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
71361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
71461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
71561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
71661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
71761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                showHeaders(true);
71861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
71961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
72061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSceneWithoutHeaders =  sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
72161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
72261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void run() {
72361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                showHeaders(false);
72461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
72561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
726c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mSceneAfterEntranceTransition = sTransitionHelper.createScene(mBrowseFrame, new Runnable() {
727c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            @Override
728c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            public void run() {
729c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                setEntranceTransitionEndState();
730c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
731c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        });
73261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitleUpTransition = TitleTransitionHelper.createTransitionTitleUp(sTransitionHelper);
73361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitleDownTransition = TitleTransitionHelper.createTransitionTitleDown(sTransitionHelper);
73461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
73561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.excludeChildren(mTitleUpTransition, R.id.browse_headers, true);
73661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.excludeChildren(mTitleDownTransition, R.id.browse_headers, true);
73761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.excludeChildren(mTitleUpTransition, R.id.container_list, true);
73861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.excludeChildren(mTitleDownTransition, R.id.container_list, true);
73961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
74061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (savedInstanceState != null) {
74161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mShowingTitle = savedInstanceState.getBoolean(TITLE_SHOW);
74261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
74361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitleView.setVisibility(mShowingTitle ? View.VISIBLE: View.INVISIBLE);
74461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
74561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return root;
74661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
74761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
748c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    @Override
749c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    public void onViewCreated(View view, Bundle savedInstanceState) {
750c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        super.onViewCreated(view, savedInstanceState);
751c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (mStartEntranceTransitionPending) {
752c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            mStartEntranceTransitionPending = false;
753c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            startEntranceTransition();
754c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
755c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
756c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
75761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void createHeadersTransition() {
75861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersTransition = sTransitionHelper.createTransitionSet(false);
75961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.excludeChildren(mHeadersTransition, R.id.browse_title_group, true);
76061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        Object changeBounds = sTransitionHelper.createChangeBounds(false);
76161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        Object fadeIn = sTransitionHelper.createFadeTransition(TransitionHelper.FADE_IN);
76261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        Object fadeOut = sTransitionHelper.createFadeTransition(TransitionHelper.FADE_OUT);
76361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        Object scale = sTransitionHelper.createScale();
76461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (TransitionHelper.systemSupportsTransitions()) {
76561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            Context context = getView().getContext();
76661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            sTransitionHelper.setInterpolator(changeBounds,
76761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    sTransitionHelper.createDefaultInterpolator(context));
76861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            sTransitionHelper.setInterpolator(fadeIn,
76961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    sTransitionHelper.createDefaultInterpolator(context));
77061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            sTransitionHelper.setInterpolator(fadeOut,
77161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    sTransitionHelper.createDefaultInterpolator(context));
77261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            sTransitionHelper.setInterpolator(scale,
77361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    sTransitionHelper.createDefaultInterpolator(context));
77461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
77561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
77661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setDuration(fadeOut, mHeadersTransitionDuration);
77761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.addTransition(mHeadersTransition, fadeOut);
77861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
77961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mShowingHeaders) {
78061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            sTransitionHelper.setStartDelay(changeBounds, mHeadersTransitionStartDelay);
78161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            sTransitionHelper.setStartDelay(scale, mHeadersTransitionStartDelay);
78261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
78361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setDuration(changeBounds, mHeadersTransitionDuration);
78461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.addTransition(mHeadersTransition, changeBounds);
7853595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        sTransitionHelper.addTarget(scale, mRowsSupportFragment.getScaleView());
78661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setDuration(scale, mHeadersTransitionDuration);
78761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.addTransition(mHeadersTransition, scale);
78861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
78961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setDuration(fadeIn, mHeadersTransitionDuration);
79061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setStartDelay(fadeIn, mHeadersTransitionStartDelay);
79161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.addTransition(mHeadersTransition, fadeIn);
79261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
79361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        sTransitionHelper.setTransitionListener(mHeadersTransition, new TransitionListener() {
79461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
79561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onTransitionStart(Object transition) {
79661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
79761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
79861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onTransitionEnd(Object transition) {
79961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersTransition = null;
80061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mRowsSupportFragment.onTransitionEnd();
80161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.onTransitionEnd();
80261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mShowingHeaders) {
80361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    VerticalGridView headerGridView = mHeadersSupportFragment.getVerticalGridView();
80461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (headerGridView != null && !headerGridView.hasFocus()) {
80561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        headerGridView.requestFocus();
80661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
80761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                } else {
80861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    VerticalGridView rowsGridView = mRowsSupportFragment.getVerticalGridView();
80961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (rowsGridView != null && !rowsGridView.hasFocus()) {
81061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        rowsGridView.requestFocus();
81161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
81261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
81361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mBrowseTransitionListener != null) {
81461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mBrowseTransitionListener.onHeadersTransitionStop(mShowingHeaders);
81561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
81661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
81761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        });
81861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
81961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
82061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
82161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the {@link PresenterSelector} used to render the row headers.
82261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
82361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headerPresenterSelector The PresenterSelector that will determine
82461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *        the Presenter for each row header.
82561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
82661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setHeaderPresenterSelector(PresenterSelector headerPresenterSelector) {
82761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeaderPresenterSelector = headerPresenterSelector;
82861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHeadersSupportFragment != null) {
82961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector);
83061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
83161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
83261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
833c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void setRowsAlignedLeft(boolean alignLeft) {
83461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        MarginLayoutParams lp;
83561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        View containerList;
83661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList = mRowsSupportFragment.getView();
83761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        lp = (MarginLayoutParams) containerList.getLayoutParams();
838c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        lp.leftMargin = alignLeft ? 0 : mContainerListMarginLeft;
83961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList.setLayoutParams(lp);
840c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
84161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
842c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void setHeadersOnScreen(boolean onScreen) {
843c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        MarginLayoutParams lp;
844c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        View containerList;
84561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList = mHeadersSupportFragment.getView();
84661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        lp = (MarginLayoutParams) containerList.getLayoutParams();
847c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        lp.leftMargin = onScreen ? 0 : -mContainerListMarginLeft;
84861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        containerList.setLayoutParams(lp);
849c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
85061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
851c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void showHeaders(boolean show) {
852c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (DEBUG) Log.v(TAG, "showHeaders " + show);
853c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mHeadersSupportFragment.setHeadersEnabled(show);
854c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(show);
855c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setRowsAlignedLeft(!show);
85661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setExpand(!show);
85761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
85861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
85961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private HeadersSupportFragment.OnHeaderClickedListener mHeaderClickedListener =
86061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        new HeadersSupportFragment.OnHeaderClickedListener() {
86161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
86261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onHeaderClicked() {
86361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mCanShowHeaders || !mShowingHeaders || isInHeadersTransition()) {
86461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return;
86561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
86661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startHeadersTransitionInternal(false);
86761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mRowsSupportFragment.getVerticalGridView().requestFocus();
86861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
86961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
87061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
87161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemViewSelectedListener mRowViewSelectedListener = new OnItemViewSelectedListener() {
87261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
87361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
87461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                RowPresenter.ViewHolder rowViewHolder, Row row) {
87561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int position = mRowsSupportFragment.getVerticalGridView().getSelectedPosition();
87661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "row selected position " + position);
87761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            onRowSelected(position);
87861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalOnItemViewSelectedListener != null) {
87961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
88061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        rowViewHolder, row);
88161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
88261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
88361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
88461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
88561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemSelectedListener mRowSelectedListener = new OnItemSelectedListener() {
88661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
88761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onItemSelected(Object item, Row row) {
88861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mExternalOnItemSelectedListener != null) {
88961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mExternalOnItemSelectedListener.onItemSelected(item, row);
89061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
89161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
89261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
89361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
89461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnItemSelectedListener mHeaderSelectedListener = new OnItemSelectedListener() {
89561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
89661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onItemSelected(Object item, Row row) {
89761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int position = mHeadersSupportFragment.getVerticalGridView().getSelectedPosition();
89861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "header selected position " + position);
89961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            onRowSelected(position);
90061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
90161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
90261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
90361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void onRowSelected(int position) {
90461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (position != mSelectedPosition) {
90561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mSetSelectionRunnable.mPosition = position;
90661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mBrowseFrame.getHandler().post(mSetSelectionRunnable);
90761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
90861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (getAdapter() == null || getAdapter().size() == 0 || position == 0) {
90961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (!mShowingTitle) {
91061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
91161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingTitle = true;
91261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
91361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else if (mShowingTitle) {
91461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
91561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mShowingTitle = false;
91661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
91761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
91861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
91961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
92061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private class SetSelectionRunnable implements Runnable {
92161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        int mPosition;
92261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
92361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void run() {
92461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setSelection(mPosition);
92561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
92661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
92761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
92861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
92961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
93061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void setSelection(int position) {
93161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (position != NO_POSITION) {
93261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.setSelectedPosition(position);
93361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.setSelectedPosition(position);
93461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
93561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mSelectedPosition = position;
93661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
93761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
93861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
93961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onStart() {
94061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onStart();
94161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setWindowAlignmentFromTop(mContainerListAlignTop);
94261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersSupportFragment.setItemAlignment();
94361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setWindowAlignmentFromTop(mContainerListAlignTop);
94461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRowsSupportFragment.setItemAlignment();
94561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
9463595aa0cbdaa8e754365ca94a0b9eb8fc52b9796Dake Gu        mRowsSupportFragment.setScalePivots(0, mContainerListAlignTop);
94761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
94861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mCanShowHeaders && mShowingHeaders && mHeadersSupportFragment.getView() != null) {
94961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersSupportFragment.getView().requestFocus();
95061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else if ((!mCanShowHeaders || !mShowingHeaders)
95161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                && mRowsSupportFragment.getView() != null) {
95261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRowsSupportFragment.getView().requestFocus();
95361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
95461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mCanShowHeaders) {
95561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            showHeaders(mShowingHeaders);
95661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
957c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (mEntranceTransitionEnabled) {
958c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            setEntranceTransitionStartState();
959c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
96061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
96161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
96261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
96361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Enable/disable headers transition on back key support. This is enabled by
96461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * default. The BrowseSupportFragment will add a back stack entry when headers are
96561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * showing. Running a headers transition when the back key is pressed only
96661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * works when the headers state is {@link #HEADERS_ENABLED} or
96761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link #HEADERS_HIDDEN}.
96861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * <p>
96961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * NOTE: If an Activity has its own onBackPressed() handling, you must
97061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * disable this feature. You may use {@link #startHeadersTransition(boolean)}
97161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * and {@link BrowseTransitionListener} in your own back stack handling.
97261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
97361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public final void setHeadersTransitionOnBackEnabled(boolean headersBackStackEnabled) {
97461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mHeadersBackStackEnabled = headersBackStackEnabled;
97561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
97661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
97761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
97861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if headers transition on back key support is enabled.
97961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
98061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public final boolean isHeadersTransitionOnBackEnabled() {
98161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersBackStackEnabled;
98261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
98361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
98461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void readArguments(Bundle args) {
98561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args == null) {
98661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
98761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
98861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args.containsKey(ARG_TITLE)) {
98961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setTitle(args.getString(ARG_TITLE));
99061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
99161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (args.containsKey(ARG_HEADERS_STATE)) {
99261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setHeadersState(args.getInt(ARG_HEADERS_STATE));
99361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
99461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
99561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
99661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
99761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the drawable displayed in the browse fragment title.
99861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
99961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param drawable The Drawable to display in the browse fragment title.
100061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
100161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBadgeDrawable(Drawable drawable) {
100261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mBadgeDrawable != drawable) {
100361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mBadgeDrawable = drawable;
100461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mTitleView != null) {
100561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mTitleView.setBadgeDrawable(drawable);
100661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
100761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
100861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
100961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
101061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
101161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the badge drawable used in the fragment title.
101261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
101361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public Drawable getBadgeDrawable() {
101461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mBadgeDrawable;
101561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
101661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
101761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
101861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets a title for the browse fragment.
101961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
102061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param title The title of the browse fragment.
102161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
102261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setTitle(String title) {
102361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mTitle = title;
102461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mTitleView != null) {
102561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mTitleView.setTitle(title);
102661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
102761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
102861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
102961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
103061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the title for the browse fragment.
103161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
103261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public String getTitle() {
103361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mTitle;
103461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
103561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
103661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
103761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the state for the headers column in the browse fragment. Must be one
103861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * of {@link #HEADERS_ENABLED}, {@link #HEADERS_HIDDEN}, or
103961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * {@link #HEADERS_DISABLED}.
104061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
104161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param headersState The state of the headers for the browse fragment.
104261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
104361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setHeadersState(int headersState) {
104461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (headersState < HEADERS_ENABLED || headersState > HEADERS_DISABLED) {
104561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalArgumentException("Invalid headers state: " + headersState);
104661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
104761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "setHeadersState " + headersState);
104861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
104961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (headersState != mHeadersState) {
105061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHeadersState = headersState;
105161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            switch (headersState) {
105261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_ENABLED:
105361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = true;
105461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = true;
105561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
105661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_HIDDEN:
105761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = true;
105861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = false;
105961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
106061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case HEADERS_DISABLED:
106161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mCanShowHeaders = false;
106261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mShowingHeaders = false;
106361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
106461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                default:
106561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    Log.w(TAG, "Unknown headers state: " + headersState);
106661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    break;
106761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
106861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mHeadersSupportFragment != null) {
106961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders);
107061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
107161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
107261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
107361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
107461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
107561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the state of the headers column in the browse fragment.
107661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
107761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getHeadersState() {
107861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mHeadersState;
107961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
1080c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1081c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    /**
1082c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * Enable or disable entrance transition.  Typically this is set in onCreate()
1083c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * when savedInstance is null.  When the entrance transition is enabled, the
1084c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * fragment is initially having headers and content hidden.
1085c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * When data of rows are ready, you must call startEntranceTransition() to kick off
1086c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * the transition.
1087c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     */
1088c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    public void setEntranceTransitionEnabled(boolean runEntranceTransition) {
1089c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mEntranceTransitionEnabled = runEntranceTransition;
1090c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1091c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1092c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    /**
1093c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * Return true if entrance transition is enabled and not started yet.
1094c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     */
1095c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    public boolean isEntranceTransitionEnabled() {
1096c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        return mEntranceTransitionEnabled;
1097c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1098c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1099c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    /**
1100c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * Starts entrance transition if setEntranceTransitionEnabled(true) is called
1101c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * and entrance transition is not started yet.
1102c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * When fragment finishes loading data of rows, it should call startEntranceTransition()
1103c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * to execute the entrance transition.  Calling startEntranceTransition() multiple
1104c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     * times is safe.
1105c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu     */
1106c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    public void startEntranceTransition() {
1107c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (!mEntranceTransitionEnabled || mEntranceTransition != null) {
1108c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            return;
1109c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
1110c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        // if view is not created yet, delay until onViewCreated()
1111c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (getView() == null) {
1112c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            mStartEntranceTransitionPending = true;
1113c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            return;
1114c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
1115c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        // wait till views get their initial position before start transition
1116c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        final View view = getView();
1117c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        view.getViewTreeObserver().addOnPreDrawListener(
1118c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                new ViewTreeObserver.OnPreDrawListener() {
1119c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            @Override
1120c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            public boolean onPreDraw() {
1121c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                view.getViewTreeObserver().removeOnPreDrawListener(this);
1122c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                createEntranceTransition();
1123c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                mEntranceTransitionEnabled = false;
1124c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                sTransitionHelper.runTransition(mSceneAfterEntranceTransition,
1125c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                        mEntranceTransition);
1126c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                return false;
1127c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
1128c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        });
1129c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        view.invalidate();
1130c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1131c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1132c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void createEntranceTransition() {
1133c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mEntranceTransition = sTransitionHelper.loadTransition(getActivity(),
1134c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                R.transition.lb_browse_entrance_transition);
1135c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        if (mEntranceTransition == null) {
1136c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            return;
1137c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        }
1138c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        sTransitionHelper.setTransitionListener(mEntranceTransition, new TransitionListener() {
1139c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            @Override
1140c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            public void onTransitionStart(Object transition) {
1141c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                mHeadersSupportFragment.onTransitionStart();
1142c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                mRowsSupportFragment.onTransitionStart();
1143c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
1144c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            @Override
1145c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            public void onTransitionEnd(Object transition) {
1146c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                mRowsSupportFragment.onTransitionEnd();
1147c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                mHeadersSupportFragment.onTransitionEnd();
1148c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu                mEntranceTransition = null;
1149c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu            }
1150c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        });
1151c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1152c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1153c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    private void setSearchOrbViewOnScreen(boolean onScreen) {
1154c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        View searchOrbView = mTitleView.getSearchAffordanceView();
1155c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        MarginLayoutParams lp = (MarginLayoutParams) searchOrbView.getLayoutParams();
1156c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        lp.leftMargin = onScreen ? 0 : -mContainerListMarginLeft;
1157c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        searchOrbView.setLayoutParams(lp);
1158c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1159c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1160c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void setEntranceTransitionStartState() {
1161c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(false);
1162c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setSearchOrbViewOnScreen(false);
1163c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mRowsSupportFragment.setViewsVisible(false);
1164c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1165c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
1166c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    void setEntranceTransitionEndState() {
1167c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setHeadersOnScreen(mShowingHeaders);
1168c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        setSearchOrbViewOnScreen(true);
1169c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        mRowsSupportFragment.setViewsVisible(true);
1170c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
1171c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu
117261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu}
117361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
1174