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