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; 21bb0a680c10b84b83833a59634373140f8bd0750csusnataimport android.support.v4.app.FragmentTransaction; 222f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.content.res.TypedArray; 232f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.graphics.Color; 242f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.graphics.Rect; 252f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.os.Bundle; 2670acb0c19be3831a2080e4f902324de16bfbf62eTor Norbyeimport android.support.annotation.ColorInt; 2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.R; 2861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionHelper; 2961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.transition.TransitionListener; 3061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.BrowseFrameLayout; 318ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Guimport android.support.v17.leanback.widget.InvisibleRowPresenter; 321c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnataimport android.support.v17.leanback.widget.ListRow; 332f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v17.leanback.widget.ObjectAdapter; 3461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewClickedListener; 3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.OnItemViewSelectedListener; 361c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnataimport android.support.v17.leanback.widget.PageRow; 3761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.Presenter; 3861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.PresenterSelector; 392f5ebf3f6f7bb6a24856f389e369b247118ba119susnataimport android.support.v17.leanback.widget.Row; 408df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Guimport android.support.v17.leanback.widget.RowHeaderPresenter; 4161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.RowPresenter; 42a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnataimport android.support.v17.leanback.widget.ScaleFrameLayout; 43a373804d10f93a9488adc35cf6ce44dce09b3778Dake Guimport android.support.v17.leanback.widget.TitleViewAdapter; 4461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.VerticalGridView; 458e3566285de4ac771d6188f62fe947e23d371a3dKris Giesingimport android.support.v4.view.ViewCompat; 46041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Guimport android.support.v7.widget.RecyclerView; 4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log; 4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.LayoutInflater; 4961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View; 5061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup; 5161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup.MarginLayoutParams; 52a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnataimport android.view.ViewTreeObserver; 5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 54fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basakimport java.util.HashMap; 55fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basakimport java.util.Map; 56fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 57b3756c53c5be55e8c8a2f6e2cda264407be84881susnataimport static android.support.v7.widget.RecyclerView.NO_POSITION; 58b3756c53c5be55e8c8a2f6e2cda264407be84881susnata 5961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/** 6061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A fragment for creating Leanback browse screens. It is composed of a 6161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * RowsSupportFragment and a HeadersSupportFragment. 6261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p> 6361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A BrowseSupportFragment renders the elements of its {@link ObjectAdapter} as a set 6461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of rows in a vertical list. The elements in this adapter must be subclasses 6561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of {@link Row}. 6661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p> 6761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * The HeadersSupportFragment can be set to be either shown or hidden by default, or 6861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * may be disabled entirely. See {@link #setHeadersState} for details. 6961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p> 7061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * By default the BrowseSupportFragment includes support for returning to the headers 7161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * when the user presses Back. For Activities that customize {@link 726193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu * android.support.v4.app.FragmentActivity#onBackPressed()}, you must disable this default Back key support by 7361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * calling {@link #setHeadersTransitionOnBackEnabled(boolean)} with false and 7461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * use {@link BrowseSupportFragment.BrowseTransitionListener} and 7561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * {@link #startHeadersTransition(boolean)}. 76a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p> 77a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * The recommended theme to use with a BrowseSupportFragment is 78a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link android.support.v17.leanback.R.style#Theme_Leanback_Browse}. 79a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p> 8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 813f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gupublic class BrowseSupportFragment extends BaseSupportFragment { 8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 8361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // BUNDLE attribute for saving header show/hide status when backstack is used: 8461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu static final String HEADER_STACK_INDEX = "headerStackIndex"; 8561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // BUNDLE attribute for saving header show/hide status when backstack is not used: 8661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu static final String HEADER_SHOW = "headerShow"; 87fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private static final String IS_PAGE_ROW = "isPageRow"; 88fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private static final String CURRENT_SELECTED_POSITION = "currentSelectedPosition"; 89e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout 9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu final class BackStackListener implements FragmentManager.OnBackStackChangedListener { 9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int mLastEntryCount; 9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int mIndexOfHeadersBackStack; 9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 9461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu BackStackListener() { 9561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mLastEntryCount = getFragmentManager().getBackStackEntryCount(); 9661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mIndexOfHeadersBackStack = -1; 9761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 9861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 9961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void load(Bundle savedInstanceState) { 10061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (savedInstanceState != null) { 10161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mIndexOfHeadersBackStack = savedInstanceState.getInt(HEADER_STACK_INDEX, -1); 10261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mShowingHeaders = mIndexOfHeadersBackStack == -1; 10361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 10461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (!mShowingHeaders) { 10561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getFragmentManager().beginTransaction() 10661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu .addToBackStack(mWithHeadersBackStackName).commit(); 10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu void save(Bundle outState) { 11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu outState.putInt(HEADER_STACK_INDEX, mIndexOfHeadersBackStack); 11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onBackStackChanged() { 11861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (getFragmentManager() == null) { 11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu Log.w(TAG, "getFragmentManager() is null, stack:", new Exception()); 12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int count = getFragmentManager().getBackStackEntryCount(); 12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // if backstack is growing and last pushed entry is "headers" backstack, 12461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // remember the index of the entry. 12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (count > mLastEntryCount) { 12661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu BackStackEntry entry = getFragmentManager().getBackStackEntryAt(count - 1); 12761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mWithHeadersBackStackName.equals(entry.getName())) { 12861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mIndexOfHeadersBackStack = count - 1; 12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else if (count < mLastEntryCount) { 13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // if popped "headers" backstack, initiate the show header transition if needed 13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mIndexOfHeadersBackStack >= count) { 13369381509eace8e71ba4886e9e1e78cda62b66516Dake Gu if (!isHeadersDataReady()) { 134b3756c53c5be55e8c8a2f6e2cda264407be84881susnata // if main fragment was restored first before BrowseSupportFragment's adapter gets 135b3756c53c5be55e8c8a2f6e2cda264407be84881susnata // restored: don't start header transition, but add the entry back. 13669381509eace8e71ba4886e9e1e78cda62b66516Dake Gu getFragmentManager().beginTransaction() 13769381509eace8e71ba4886e9e1e78cda62b66516Dake Gu .addToBackStack(mWithHeadersBackStackName).commit(); 13869381509eace8e71ba4886e9e1e78cda62b66516Dake Gu return; 13969381509eace8e71ba4886e9e1e78cda62b66516Dake Gu } 14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mIndexOfHeadersBackStack = -1; 14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (!mShowingHeaders) { 14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu startHeadersTransitionInternal(true); 14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 14661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mLastEntryCount = count; 14761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 14861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 14961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 15061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Listener for transitions between browse headers and rows. 15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public static class BrowseTransitionListener { 15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Callback when headers transition starts. 15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 15761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param withHeaders True if the transition will result in headers 15861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * being shown, false otherwise. 15961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 16061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onHeadersTransitionStart(boolean withHeaders) { 16161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 16261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 16361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Callback when headers transition stops. 16461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 16561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param withHeaders True if the transition will result in headers 16661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * being shown, false otherwise. 16761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 16861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onHeadersTransitionStop(boolean withHeaders) { 16961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 17061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 17161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 172aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout private class SetSelectionRunnable implements Runnable { 173aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout static final int TYPE_INVALID = -1; 174aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout static final int TYPE_INTERNAL_SYNC = 0; 175aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout static final int TYPE_USER_REQUEST = 1; 176aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout 177aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout private int mPosition; 178aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout private int mType; 179aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout private boolean mSmooth; 180aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout 181aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout SetSelectionRunnable() { 182aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout reset(); 183aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout } 184aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout 185aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout void post(int position, int type, boolean smooth) { 186aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout // Posting the set selection, rather than calling it immediately, prevents an issue 187aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout // with adapter changes. Example: a row is added before the current selected row; 188aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout // first the fast lane view updates its selection, then the rows fragment has that 189aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout // new selection propagated immediately; THEN the rows view processes the same adapter 190aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout // change and moves the selection again. 191aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout if (type >= mType) { 192aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mPosition = position; 193aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mType = type; 194aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mSmooth = smooth; 195aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mBrowseFrame.removeCallbacks(this); 196aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mBrowseFrame.post(this); 197aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout } 198aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout } 199aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout 200aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout @Override 201aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout public void run() { 202aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout setSelection(mPosition, mSmooth); 203aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout reset(); 204aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout } 205aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout 206aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout private void reset() { 207aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mPosition = -1; 208aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mType = TYPE_INVALID; 209aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mSmooth = false; 210aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout } 211aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout } 212aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout 2131c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata /** 214cabb8eca86d0248274f57008ff66427fec2e927csusnata * Possible set of actions that {@link BrowseSupportFragment} exposes to clients. Custom 215cabb8eca86d0248274f57008ff66427fec2e927csusnata * fragments can interact with {@link BrowseSupportFragment} using this interface. 216cabb8eca86d0248274f57008ff66427fec2e927csusnata */ 217cabb8eca86d0248274f57008ff66427fec2e927csusnata public interface FragmentHost { 218cabb8eca86d0248274f57008ff66427fec2e927csusnata /** 219a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * Fragments are required to invoke this callback once their view is created 220a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * inside {@link Fragment#onViewCreated} method. {@link BrowseSupportFragment} starts the entrance 221cabb8eca86d0248274f57008ff66427fec2e927csusnata * animation only after receiving this callback. Failure to invoke this method 222cabb8eca86d0248274f57008ff66427fec2e927csusnata * will lead to fragment not showing up. 223cabb8eca86d0248274f57008ff66427fec2e927csusnata * 224cabb8eca86d0248274f57008ff66427fec2e927csusnata * @param fragmentAdapter {@link MainFragmentAdapter} used by the current fragment. 225cabb8eca86d0248274f57008ff66427fec2e927csusnata */ 226cabb8eca86d0248274f57008ff66427fec2e927csusnata void notifyViewCreated(MainFragmentAdapter fragmentAdapter); 2276fd4441435b14669deced90a05097dd5fe459acesusnata 2286fd4441435b14669deced90a05097dd5fe459acesusnata /** 229a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * Fragments mapped to {@link PageRow} are required to invoke this callback once their data 230a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * is created for transition, the entrance animation only after receiving this callback. 231a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * Failure to invoke this method will lead to fragment not showing up. 232a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * 233a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu * @param fragmentAdapter {@link MainFragmentAdapter} used by the current fragment. 234a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu */ 235a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu void notifyDataReady(MainFragmentAdapter fragmentAdapter); 236a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu 237a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu /** 238a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * Show or hide title view in {@link BrowseSupportFragment} for fragments mapped to 239a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * {@link PageRow}. Otherwise the request is ignored, in that case BrowseSupportFragment is fully 240a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * in control of showing/hiding title view. 241a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * <p> 242a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * When HeadersSupportFragment is visible, BrowseSupportFragment will hide search affordance view if 243a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * there are other focusable rows above currently focused row. 2446fd4441435b14669deced90a05097dd5fe459acesusnata * 2456fd4441435b14669deced90a05097dd5fe459acesusnata * @param show Boolean indicating whether or not to show the title view. 2466fd4441435b14669deced90a05097dd5fe459acesusnata */ 2476fd4441435b14669deced90a05097dd5fe459acesusnata void showTitleView(boolean show); 248cabb8eca86d0248274f57008ff66427fec2e927csusnata } 249cabb8eca86d0248274f57008ff66427fec2e927csusnata 250cabb8eca86d0248274f57008ff66427fec2e927csusnata /** 251cabb8eca86d0248274f57008ff66427fec2e927csusnata * Default implementation of {@link FragmentHost} that is used only by 252cabb8eca86d0248274f57008ff66427fec2e927csusnata * {@link BrowseSupportFragment}. 253cabb8eca86d0248274f57008ff66427fec2e927csusnata */ 254cabb8eca86d0248274f57008ff66427fec2e927csusnata private final class FragmentHostImpl implements FragmentHost { 2557350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata boolean mShowTitleView = true; 256a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu boolean mDataReady = false; 257cabb8eca86d0248274f57008ff66427fec2e927csusnata 25899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas FragmentHostImpl() { 25999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas } 26099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas 261cabb8eca86d0248274f57008ff66427fec2e927csusnata @Override 262cabb8eca86d0248274f57008ff66427fec2e927csusnata public void notifyViewCreated(MainFragmentAdapter fragmentAdapter) { 263a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu performPendingStates(); 264a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu } 265a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu 266a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu @Override 267a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu public void notifyDataReady(MainFragmentAdapter fragmentAdapter) { 268a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu mDataReady = true; 269a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu 270a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu // If fragment host is not the currently active fragment (in BrowseSupportFragment), then 271a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu // ignore the request. 272a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu if (mMainFragmentAdapter == null || mMainFragmentAdapter.getFragmentHost() != this) { 273a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu return; 274a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu } 275a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu 276a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu // We only honor showTitle request for PageRows. 277a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu if (!mIsPageRow) { 278a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu return; 279a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu } 280a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu 281a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu performPendingStates(); 282cabb8eca86d0248274f57008ff66427fec2e927csusnata } 2836fd4441435b14669deced90a05097dd5fe459acesusnata 2846fd4441435b14669deced90a05097dd5fe459acesusnata @Override 2856fd4441435b14669deced90a05097dd5fe459acesusnata public void showTitleView(boolean show) { 2867350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mShowTitleView = show; 287d0fc2e48059f718676a531af06a31849f54c1ca9susnata 288d0fc2e48059f718676a531af06a31849f54c1ca9susnata // If fragment host is not the currently active fragment (in BrowseSupportFragment), then 289d0fc2e48059f718676a531af06a31849f54c1ca9susnata // ignore the request. 290d0fc2e48059f718676a531af06a31849f54c1ca9susnata if (mMainFragmentAdapter == null || mMainFragmentAdapter.getFragmentHost() != this) { 291d0fc2e48059f718676a531af06a31849f54c1ca9susnata return; 292b10ba3b01290ce801180a3d5dc992825af8cb3absusnata } 293d0fc2e48059f718676a531af06a31849f54c1ca9susnata 294d0fc2e48059f718676a531af06a31849f54c1ca9susnata // We only honor showTitle request for PageRows. 295d0fc2e48059f718676a531af06a31849f54c1ca9susnata if (!mIsPageRow) { 296d0fc2e48059f718676a531af06a31849f54c1ca9susnata return; 297d0fc2e48059f718676a531af06a31849f54c1ca9susnata } 298d0fc2e48059f718676a531af06a31849f54c1ca9susnata 2998ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu updateTitleViewVisibility(); 3006fd4441435b14669deced90a05097dd5fe459acesusnata } 301cabb8eca86d0248274f57008ff66427fec2e927csusnata } 302cabb8eca86d0248274f57008ff66427fec2e927csusnata 303cabb8eca86d0248274f57008ff66427fec2e927csusnata /** 3041c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * Interface that defines the interaction between {@link BrowseSupportFragment} and it's main 305fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * content fragment. The key method is {@link MainFragmentAdapter#getFragment()}, 3061c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * it will be used to get the fragment to be shown in the content section. Clients can 3071c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * provide any implementation of fragment and customize it's interaction with 3081c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * {@link BrowseSupportFragment} by overriding the necessary methods. 3091c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * 3101c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * <p> 3111c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * Clients are expected to provide 312fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * an instance of {@link MainFragmentAdapterRegistry} which will be responsible for providing 313fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * implementations of {@link MainFragmentAdapter} for given content types. Currently 3141c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * we support different types of content - {@link ListRow}, {@link PageRow} or any subtype 3151c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * of {@link Row}. We provide an out of the box adapter implementation for any rows other than 316fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * {@link PageRow} - {@link android.support.v17.leanback.app.RowsSupportFragment.MainFragmentAdapter}. 3171c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * 3181c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * <p> 3191c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * {@link PageRow} is intended to give full flexibility to developers in terms of Fragment 320fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * design. Users will have to provide an implementation of {@link MainFragmentAdapter} 321fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * and provide that through {@link MainFragmentAdapterRegistry}. 322fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * {@link MainFragmentAdapter} implementation can supply any fragment and override 3231c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * just those interactions that makes sense. 3241c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata */ 325fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public static class MainFragmentAdapter<T extends Fragment> { 326f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata private boolean mScalingEnabled; 327fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private final T mFragment; 32899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas FragmentHostImpl mFragmentHost; 329fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 330fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public MainFragmentAdapter(T fragment) { 331fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak this.mFragment = fragment; 332fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 333fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 334fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public final T getFragment() { 335fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak return mFragment; 336fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 3372f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3382f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3392f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * Returns whether its scrolling. 3402f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3411c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public boolean isScrolling() { 3421c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata return false; 3431c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 3442f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3452f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3462f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * Set the visibility of titles/hovercard of browse rows. 3472f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3481c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public void setExpand(boolean expand) { 3491c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 3502f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3512f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3522f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * For rows that willing to participate entrance transition, this function 3532f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * hide views if afterTransition is true, show views if afterTransition is false. 3542f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3551c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public void setEntranceTransitionState(boolean state) { 3561c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 3572f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3582f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3592f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * Sets the window alignment and also the pivots for scale operation. 3602f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3611c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public void setAlignment(int windowAlignOffsetFromTop) { 3621c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 3632f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3642f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3652f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * Callback indicating transition prepare start. 3662f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3671c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public boolean onTransitionPrepare() { 3681c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata return false; 3691c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 3702f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3712f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3722f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * Callback indicating transition start. 3732f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3741c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public void onTransitionStart() { 3751c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 3762f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 3772f5ebf3f6f7bb6a24856f389e369b247118ba119susnata /** 3782f5ebf3f6f7bb6a24856f389e369b247118ba119susnata * Callback indicating transition end. 3792f5ebf3f6f7bb6a24856f389e369b247118ba119susnata */ 3801c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata public void onTransitionEnd() { 3811c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 382f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata 383f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata /** 384f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * Returns whether row scaling is enabled. 385f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata */ 386f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata public boolean isScalingEnabled() { 387f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata return mScalingEnabled; 388f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata } 389f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata 390f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata /** 391f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * Sets the row scaling property. 392f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata */ 393f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata public void setScalingEnabled(boolean scalingEnabled) { 394f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata this.mScalingEnabled = scalingEnabled; 395f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata } 396cabb8eca86d0248274f57008ff66427fec2e927csusnata 3977350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata /** 3987350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata * Returns the current host interface so that main fragment can interact with 3997350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata * {@link BrowseSupportFragment}. 4007350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata */ 401cabb8eca86d0248274f57008ff66427fec2e927csusnata public final FragmentHost getFragmentHost() { 402cabb8eca86d0248274f57008ff66427fec2e927csusnata return mFragmentHost; 403cabb8eca86d0248274f57008ff66427fec2e927csusnata } 4047350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 4057350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata void setFragmentHost(FragmentHostImpl fragmentHost) { 4067350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata this.mFragmentHost = fragmentHost; 4077350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } 4082f5ebf3f6f7bb6a24856f389e369b247118ba119susnata } 4092f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 4101c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata /** 411d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * Interface to be implemented by all fragments for providing an instance of 412d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * {@link MainFragmentAdapter}. Both {@link RowsSupportFragment} and custom fragment provided 413d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * against {@link PageRow} will need to implement this interface. 414d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata */ 415d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata public interface MainFragmentAdapterProvider { 416d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata /** 417d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * Returns an instance of {@link MainFragmentAdapter} that {@link BrowseSupportFragment} 418d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * would use to communicate with the target fragment. 419d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata */ 420d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata MainFragmentAdapter getMainFragmentAdapter(); 421d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } 422d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata 423d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata /** 424d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * Interface to be implemented by {@link RowsSupportFragment} and it's subclasses for providing 425d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * an instance of {@link MainFragmentRowsAdapter}. 426d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata */ 427d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata public interface MainFragmentRowsAdapterProvider { 428d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata /** 429d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * Returns an instance of {@link MainFragmentRowsAdapter} that {@link BrowseSupportFragment} 430d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * would use to communicate with the target fragment. 431d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata */ 432d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata MainFragmentRowsAdapter getMainFragmentRowsAdapter(); 433d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } 434d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata 435d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata /** 436d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * This is used to pass information to {@link RowsSupportFragment} or its subclasses. 437d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * {@link BrowseSupportFragment} uses this interface to pass row based interaction events to 438d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata * the target fragment. 4391c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata */ 440fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public static class MainFragmentRowsAdapter<T extends Fragment> { 441fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private final T mFragment; 442fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 443fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public MainFragmentRowsAdapter(T fragment) { 444fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (fragment == null) { 445fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak throw new IllegalArgumentException("Fragment can't be null"); 446fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 447fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak this.mFragment = fragment; 448fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 449fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 450fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public final T getFragment() { 451fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak return mFragment; 452fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 453a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 454a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata * Set the visibility titles/hover of browse rows. 455a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 456a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata public void setAdapter(ObjectAdapter adapter) { 457a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 4581c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 459a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 460a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata * Sets an item clicked listener on the fragment. 461a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 462a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata public void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 463a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 464a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata 465a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 466a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata * Sets an item selection listener. 467a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 468a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 469a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 470a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata 471a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 472a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata * Selects a Row and perform an optional task on the Row. 473a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 474a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata public void setSelectedPosition(int rowPosition, 475a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata boolean smooth, 476a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata final Presenter.ViewHolderTask rowHolderTask) { 477a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 478a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata 479a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 480a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata * Selects a Row. 481a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 482a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata public void setSelectedPosition(int rowPosition, boolean smooth) { 483a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 484a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata 485a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 486a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata * Returns the selected position. 487a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 488a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata public int getSelectedPosition() { 489a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata return 0; 490a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 491a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 4921c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 493a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata private boolean createMainFragment(ObjectAdapter adapter, int position) { 494a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata Object item = null; 495a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata if (adapter == null || adapter.size() == 0) { 496fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak return false; 497a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } else { 498bb0a680c10b84b83833a59634373140f8bd0750csusnata if (position < 0) { 499bb0a680c10b84b83833a59634373140f8bd0750csusnata position = 0; 500bb0a680c10b84b83833a59634373140f8bd0750csusnata } else if (position >= adapter.size()) { 5011c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata throw new IllegalArgumentException( 5021c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata String.format("Invalid position %d requested", position)); 5031c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 504a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata item = adapter.get(position); 505a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 5061c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 507a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu mSelectedPosition = position; 508fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak boolean oldIsPageRow = mIsPageRow; 509fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mIsPageRow = item instanceof PageRow; 510fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak boolean swap; 511fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 512fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (mMainFragment == null) { 513fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak swap = true; 514a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } else { 515fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (oldIsPageRow) { 516fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak swap = true; 517fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } else { 518fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak swap = mIsPageRow; 519fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 5201c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 521fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 522fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (swap) { 523fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragment = mMainFragmentAdapterRegistry.createFragment(item); 524d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata if (!(mMainFragment instanceof MainFragmentAdapterProvider)) { 525d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata throw new IllegalArgumentException( 526d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata "Fragment must implement MainFragmentAdapterProvider"); 527d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } 528d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata 529d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata mMainFragmentAdapter = ((MainFragmentAdapterProvider)mMainFragment) 530d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata .getMainFragmentAdapter(); 531cabb8eca86d0248274f57008ff66427fec2e927csusnata mMainFragmentAdapter.setFragmentHost(new FragmentHostImpl()); 532fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (!mIsPageRow) { 533d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata if (mMainFragment instanceof MainFragmentRowsAdapterProvider) { 534d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata mMainFragmentRowsAdapter = ((MainFragmentRowsAdapterProvider)mMainFragment) 535d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata .getMainFragmentRowsAdapter(); 536d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } else { 537d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata mMainFragmentRowsAdapter = null; 538d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } 539fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mIsPageRow = mMainFragmentRowsAdapter == null; 540fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } else { 541fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentRowsAdapter = null; 542fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 543fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 544d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata 545fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak return swap; 546a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 547a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata 548a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata /** 549fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * Factory class responsible for creating fragment given the current item. {@link ListRow} 550fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * should returns {@link RowsSupportFragment} or it's subclass whereas {@link PageRow} 551fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * can return any fragment class. 552a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata */ 553fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public abstract static class FragmentFactory<T extends Fragment> { 554fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public abstract T createFragment(Object row); 555fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 5561c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 557fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak /** 558fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * FragmentFactory implementation for {@link ListRow}. 559fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak */ 560fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public static class ListRowFragmentFactory extends FragmentFactory<RowsSupportFragment> { 561fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak @Override 562fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public RowsSupportFragment createFragment(Object row) { 563fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak return new RowsSupportFragment(); 56480a1d2dfbe5c1f26370cc1753c3ae321f126f5d2Carlos Valdivia } 565fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 5664400ca12ff731a7392715bc3d8ad3539b4c37889susnata 567fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak /** 568fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * Registry class maintaining the mapping of {@link Row} subclasses to {@link FragmentFactory}. 569fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * BrowseRowFragment automatically registers {@link ListRowFragmentFactory} for 570fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * handling {@link ListRow}. Developers can override that and also if they want to 571fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * use custom fragment, they can register a custom {@link FragmentFactory} 572fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * against {@link PageRow}. 573fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak */ 574fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public final static class MainFragmentAdapterRegistry { 575cfcb31c4895793dda843faf67d1b769268e3cce8susnata private final Map<Class, FragmentFactory> mItemToFragmentFactoryMapping = new HashMap(); 576cfcb31c4895793dda843faf67d1b769268e3cce8susnata private final static FragmentFactory sDefaultFragmentFactory = new ListRowFragmentFactory(); 577cfcb31c4895793dda843faf67d1b769268e3cce8susnata 578cfcb31c4895793dda843faf67d1b769268e3cce8susnata public MainFragmentAdapterRegistry() { 579cfcb31c4895793dda843faf67d1b769268e3cce8susnata registerFragment(ListRow.class, sDefaultFragmentFactory); 580cfcb31c4895793dda843faf67d1b769268e3cce8susnata } 581fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 582fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public void registerFragment(Class rowClass, FragmentFactory factory) { 583cfcb31c4895793dda843faf67d1b769268e3cce8susnata mItemToFragmentFactoryMapping.put(rowClass, factory); 584fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 585fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 586fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public Fragment createFragment(Object item) { 587fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (item == null) { 588fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak throw new IllegalArgumentException("Item can't be null"); 589fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 590fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 591cfcb31c4895793dda843faf67d1b769268e3cce8susnata FragmentFactory fragmentFactory = mItemToFragmentFactoryMapping.get(item.getClass()); 592cfcb31c4895793dda843faf67d1b769268e3cce8susnata if (fragmentFactory == null && !(item instanceof PageRow)) { 593cfcb31c4895793dda843faf67d1b769268e3cce8susnata fragmentFactory = sDefaultFragmentFactory; 594cfcb31c4895793dda843faf67d1b769268e3cce8susnata } 595cfcb31c4895793dda843faf67d1b769268e3cce8susnata 596cfcb31c4895793dda843faf67d1b769268e3cce8susnata return fragmentFactory.createFragment(item); 597a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 5981c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 5992f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 60099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas static final String TAG = "BrowseSupportFragment"; 60161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 60261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static final String LB_HEADERS_BACKSTACK = "lbHeadersBackStack_"; 60361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 60499ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas static boolean DEBUG = false; 60561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 60661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** The headers fragment is enabled and shown by default. */ 60761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public static final int HEADERS_ENABLED = 1; 60861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 60961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** The headers fragment is enabled and hidden by default. */ 61061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public static final int HEADERS_HIDDEN = 2; 61161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 61261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** The headers fragment is disabled and will never be shown. */ 61361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public static final int HEADERS_DISABLED = 3; 61461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 615fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private MainFragmentAdapterRegistry mMainFragmentAdapterRegistry 616fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak = new MainFragmentAdapterRegistry(); 61799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas MainFragmentAdapter mMainFragmentAdapter; 61899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas Fragment mMainFragment; 61999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas HeadersSupportFragment mHeadersSupportFragment; 620fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private MainFragmentRowsAdapter mMainFragmentRowsAdapter; 62161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 62261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private ObjectAdapter mAdapter; 6238ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu private PresenterSelector mAdapterPresenter; 6248ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu private PresenterSelector mWrappingPresenterSelector; 62561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 62661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private int mHeadersState = HEADERS_ENABLED; 62761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private int mBrandColor = Color.TRANSPARENT; 62861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private boolean mBrandColorSet; 62961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 63099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas BrowseFrameLayout mBrowseFrame; 631a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private ScaleFrameLayout mScaleFrameLayout; 63299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas boolean mHeadersBackStackEnabled = true; 63399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas String mWithHeadersBackStackName; 63499ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas boolean mShowingHeaders = true; 63599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas boolean mCanShowHeaders = true; 6368e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing private int mContainerListMarginStart; 63761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private int mContainerListAlignTop; 638f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata private boolean mMainFragmentScaleEnabled = true; 63999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas OnItemViewSelectedListener mExternalOnItemViewSelectedListener; 64061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private OnItemViewClickedListener mOnItemViewClickedListener; 641bb0a680c10b84b83833a59634373140f8bd0750csusnata private int mSelectedPosition = -1; 642f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata private float mScaleFactor; 64399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas boolean mIsPageRow; 64461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 64561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private PresenterSelector mHeaderPresenterSelector; 646aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout private final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable(); 64761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 64861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // transition related: 64999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas Object mSceneWithHeaders; 65099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas Object mSceneWithoutHeaders; 651c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu private Object mSceneAfterEntranceTransition; 65299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas Object mHeadersTransition; 65399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas BackStackListener mBackStackChangedListener; 65499ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas BrowseTransitionListener mBrowseTransitionListener; 65561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 65661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static final String ARG_TITLE = BrowseSupportFragment.class.getCanonicalName() + ".title"; 65761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private static final String ARG_HEADERS_STATE = 65861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu BrowseSupportFragment.class.getCanonicalName() + ".headersState"; 65961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 66061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 661a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Creates arguments for a browse fragment. 66261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 66361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param args The Bundle to place arguments into, or null if the method 66461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * should return a new Bundle. 66561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param title The title of the BrowseSupportFragment. 66661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param headersState The initial state of the headers of the 66761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * BrowseSupportFragment. Must be one of {@link #HEADERS_ENABLED}, {@link 66861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * #HEADERS_HIDDEN}, or {@link #HEADERS_DISABLED}. 66961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @return A Bundle with the given arguments for creating a BrowseSupportFragment. 67061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 67161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public static Bundle createArgs(Bundle args, String title, int headersState) { 67261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (args == null) { 67361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu args = new Bundle(); 67461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 67561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu args.putString(ARG_TITLE, title); 67661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu args.putInt(ARG_HEADERS_STATE, headersState); 67761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return args; 67861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 67961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 68061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 68161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets the brand color for the browse fragment. The brand color is used as 68261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the primary color for UI elements in the browse fragment. For example, 68361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the background color of the headers fragment uses the brand color. 68461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 68561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param color The color to use as the brand color of the fragment. 68661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 68770acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye public void setBrandColor(@ColorInt int color) { 68861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrandColor = color; 68961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrandColorSet = true; 69061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 69161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mHeadersSupportFragment != null) { 69261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setBackgroundColor(mBrandColor); 69361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 69461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 69561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 69661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 69761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns the brand color for the browse fragment. 69861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * The default is transparent. 69961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 70070acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye @ColorInt 70161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public int getBrandColor() { 70261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mBrandColor; 70361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 70461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 70561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 7068ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu * Wrapping app provided PresenterSelector to support InvisibleRowPresenter for SectionRow 7078ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu * DividerRow and PageRow. 7088ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu */ 7098ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu private void createAndSetWrapperPresenter() { 7108ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu final PresenterSelector adapterPresenter = mAdapter.getPresenterSelector(); 7118ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (adapterPresenter == null) { 7128ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu throw new IllegalArgumentException("Adapter.getPresenterSelector() is null"); 7138ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 7148ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (adapterPresenter == mAdapterPresenter) { 7158ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return; 7168ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 7178ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu mAdapterPresenter = adapterPresenter; 7188ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu 7198ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu Presenter[] presenters = adapterPresenter.getPresenters(); 7208ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu final Presenter invisibleRowPresenter = new InvisibleRowPresenter(); 7218ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu final Presenter[] allPresenters = new Presenter[presenters.length + 1]; 7228ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu System.arraycopy(allPresenters, 0, presenters, 0, presenters.length); 7238ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu allPresenters[allPresenters.length - 1] = invisibleRowPresenter; 7248ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu mAdapter.setPresenterSelector(new PresenterSelector() { 7258ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu @Override 7268ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu public Presenter getPresenter(Object item) { 7278ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu Row row = (Row) item; 7288ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (row.isRenderedAsRowView()) { 7298ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return adapterPresenter.getPresenter(item); 7308ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else { 7318ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return invisibleRowPresenter; 7328ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 7338ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 7348ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu 7358ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu @Override 7368ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu public Presenter[] getPresenters() { 7378ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return allPresenters; 7388ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 7398ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu }); 7408ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 7418ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu 7428ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu /** 74361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets the adapter containing the rows for the fragment. 74461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 74561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>The items referenced by the adapter must be be derived from 74661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * {@link Row}. These rows will be used by the rows fragment and the headers 74761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * fragment (if not disabled) to render the browse rows. 74861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 74961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param adapter An ObjectAdapter for the browse rows. All items must 75061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * derive from {@link Row}. 75161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 75261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setAdapter(ObjectAdapter adapter) { 75361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mAdapter = adapter; 7548ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu createAndSetWrapperPresenter(); 755c0ad3d1d9ee64cf0bdb68ac70bfb04cc919c53e6Dake Gu if (getView() == null) { 756c0ad3d1d9ee64cf0bdb68ac70bfb04cc919c53e6Dake Gu return; 757c0ad3d1d9ee64cf0bdb68ac70bfb04cc919c53e6Dake Gu } 758bb0a680c10b84b83833a59634373140f8bd0750csusnata replaceMainFragment(mSelectedPosition); 759bb0a680c10b84b83833a59634373140f8bd0750csusnata 760bb0a680c10b84b83833a59634373140f8bd0750csusnata if (adapter != null) { 761bb0a680c10b84b83833a59634373140f8bd0750csusnata if (mMainFragmentRowsAdapter != null) { 762b3756c53c5be55e8c8a2f6e2cda264407be84881susnata mMainFragmentRowsAdapter.setAdapter(new ListRowDataAdapter(adapter)); 763bb0a680c10b84b83833a59634373140f8bd0750csusnata } 76461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setAdapter(adapter); 76561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 76661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 76761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 768fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public final MainFragmentAdapterRegistry getMainFragmentRegistry() { 769fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak return mMainFragmentAdapterRegistry; 7701c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 771fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 77261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 77361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns the adapter containing the rows for the fragment. 77461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 77561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public ObjectAdapter getAdapter() { 77661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mAdapter; 77761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 77861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 77961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 78061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets an item selection listener. 78161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 78261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 78361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalOnItemViewSelectedListener = listener; 78461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 78561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 78661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 78761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns an item selection listener. 78861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 78961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public OnItemViewSelectedListener getOnItemViewSelectedListener() { 79061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mExternalOnItemViewSelectedListener; 79161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 79261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 79361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 7941c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * Get RowsSupportFragment if it's bound to BrowseSupportFragment or null if either BrowseSupportFragment has 7951c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * not been created yet or a different fragment is bound to it. 7961c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * 7971c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata * @return RowsSupportFragment if it's bound to BrowseSupportFragment or null otherwise. 7980d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu */ 7990d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu public RowsSupportFragment getRowsSupportFragment() { 8001c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata if (mMainFragment instanceof RowsSupportFragment) { 8011c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata return (RowsSupportFragment) mMainFragment; 8021c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 8031c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 8041c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata return null; 8050d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu } 8060d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu 8070d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu /** 8080d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * Get currently bound HeadersSupportFragment or null if HeadersSupportFragment has not been created yet. 8090d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * @return Currently bound HeadersSupportFragment or null if HeadersSupportFragment has not been created yet. 8100d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu */ 8110d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu public HeadersSupportFragment getHeadersSupportFragment() { 8120d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu return mHeadersSupportFragment; 8130d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu } 8140d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu 8150d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu /** 81661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets an item clicked listener on the fragment. 81761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * OnItemViewClickedListener will override {@link View.OnClickListener} that 81861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}. 819cabb8eca86d0248274f57008ff66427fec2e927csusnata * So in general, developer should choose one of the listeners but not both. 82061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 82161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 82261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mOnItemViewClickedListener = listener; 8232aff8659c7362b48f099a13ffad390bf7984dd5aJaewan Kim if (mMainFragmentRowsAdapter != null) { 824fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentRowsAdapter.setOnItemViewClickedListener(listener); 82561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 82661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 82761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 82861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 82961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns the item Clicked listener. 83061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 83161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public OnItemViewClickedListener getOnItemViewClickedListener() { 83261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mOnItemViewClickedListener; 83361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 83461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 83561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 836a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Starts a headers transition. 83761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 83861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p>This method will begin a transition to either show or hide the 83961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * headers, depending on the value of withHeaders. If headers are disabled 84061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * for this browse fragment, this method will throw an exception. 84161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 84261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param withHeaders True if the headers should transition to being shown, 84361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * false if the transition should result in headers being hidden. 84461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 84561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void startHeadersTransition(boolean withHeaders) { 84661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (!mCanShowHeaders) { 84761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu throw new IllegalStateException("Cannot start headers transition"); 84861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 84961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (isInHeadersTransition() || mShowingHeaders == withHeaders) { 85061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 85161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 85261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu startHeadersTransitionInternal(withHeaders); 85361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 85461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 85561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 85661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns true if the headers transition is currently running. 85761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 85861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public boolean isInHeadersTransition() { 85961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mHeadersTransition != null; 86061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 86161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 86261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 86361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns true if headers are shown. 86461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 86561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public boolean isShowingHeaders() { 86661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mShowingHeaders; 86761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 86861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 86961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 870a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets a listener for browse fragment transitions. 87161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 87261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param listener The listener to call when a browse headers transition 87361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * begins or ends. 87461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 87561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setBrowseTransitionListener(BrowseTransitionListener listener) { 87661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrowseTransitionListener = listener; 87761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 87861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 87961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 880f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * @deprecated use {@link BrowseSupportFragment#enableMainFragmentScaling(boolean)} instead. 88161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 88261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param enable true to enable row scaling 88361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 884d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette @Deprecated 88561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void enableRowScaling(boolean enable) { 886f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata enableMainFragmentScaling(enable); 887f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata } 888f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata 889f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata /** 890f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * Enables scaling of main fragment when headers are present. For the page/row fragment, 891f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * scaling is enabled only when both this method and 892fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak * {@link MainFragmentAdapter#isScalingEnabled()} are enabled. 893f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * 894f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata * @param enable true to enable row scaling 895f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata */ 896f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata public void enableMainFragmentScaling(boolean enable) { 897f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata mMainFragmentScaleEnabled = enable; 89861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 89961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 90099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void startHeadersTransitionInternal(final boolean withHeaders) { 90161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (getFragmentManager().isDestroyed()) { 90261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 90361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 90469381509eace8e71ba4886e9e1e78cda62b66516Dake Gu if (!isHeadersDataReady()) { 90569381509eace8e71ba4886e9e1e78cda62b66516Dake Gu return; 90669381509eace8e71ba4886e9e1e78cda62b66516Dake Gu } 90761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mShowingHeaders = withHeaders; 9081c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragmentAdapter.onTransitionPrepare(); 9091c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragmentAdapter.onTransitionStart(); 910a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata onExpandTransitionStart(!withHeaders, new Runnable() { 91161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 91261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void run() { 913902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu mHeadersSupportFragment.onTransitionPrepare(); 91461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.onTransitionStart(); 91561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu createHeadersTransition(); 91661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mBrowseTransitionListener != null) { 91761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrowseTransitionListener.onHeadersTransitionStart(withHeaders); 91861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 9191c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata TransitionHelper.runTransition( 9201c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata withHeaders ? mSceneWithHeaders : mSceneWithoutHeaders, mHeadersTransition); 92161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mHeadersBackStackEnabled) { 92261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (!withHeaders) { 92361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getFragmentManager().beginTransaction() 92461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu .addToBackStack(mWithHeadersBackStackName).commit(); 92561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 92661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu int index = mBackStackChangedListener.mIndexOfHeadersBackStack; 92761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (index >= 0) { 92861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu BackStackEntry entry = getFragmentManager().getBackStackEntryAt(index); 92961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getFragmentManager().popBackStackImmediate(entry.getId(), 93061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu FragmentManager.POP_BACK_STACK_INCLUSIVE); 93161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 93261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 93361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 93461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 93561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }); 93661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 93761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 9380d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu boolean isVerticalScrolling() { 93961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // don't run transition 9401c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata return mHeadersSupportFragment.isScrolling() || mMainFragmentAdapter.isScrolling(); 94161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 94261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 943e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout 94461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener = 94561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu new BrowseFrameLayout.OnFocusSearchListener() { 94661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 94761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public View onFocusSearch(View focused, int direction) { 94861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // if headers is running transition, focus stays 9495ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout if (mCanShowHeaders && isInHeadersTransition()) { 9505ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout return focused; 9515ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout } 95261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction); 9535ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout 954e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout if (getTitleView() != null && focused != getTitleView() && 955e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout direction == View.FOCUS_UP) { 956e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout return getTitleView(); 957e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout } 958e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout if (getTitleView() != null && getTitleView().hasFocus() && 959e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout direction == View.FOCUS_DOWN) { 9605ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout return mCanShowHeaders && mShowingHeaders ? 9611c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mHeadersSupportFragment.getVerticalGridView() : mMainFragment.getView(); 9625ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout } 9635ae73b45620a3d535b2d279512d5d34603e2bdb1Craig Stout 9648e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing boolean isRtl = ViewCompat.getLayoutDirection(focused) == View.LAYOUT_DIRECTION_RTL; 9658e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing int towardStart = isRtl ? View.FOCUS_RIGHT : View.FOCUS_LEFT; 9668e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing int towardEnd = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT; 967e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout if (mCanShowHeaders && direction == towardStart) { 96869381509eace8e71ba4886e9e1e78cda62b66516Dake Gu if (isVerticalScrolling() || mShowingHeaders || !isHeadersDataReady()) { 96961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return focused; 97061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 97161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mHeadersSupportFragment.getVerticalGridView(); 9728e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing } else if (direction == towardEnd) { 973e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout if (isVerticalScrolling()) { 97461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return focused; 975dc21f7e02936d3bf1f8e69137393814cefd9846aDake Gu } else if (mMainFragment != null && mMainFragment.getView() != null) { 976dc21f7e02936d3bf1f8e69137393814cefd9846aDake Gu return mMainFragment.getView(); 97761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 978dc21f7e02936d3bf1f8e69137393814cefd9846aDake Gu return focused; 9798ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else if (direction == View.FOCUS_DOWN && mShowingHeaders) { 9808ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu // disable focus_down moving into PageFragment. 9818ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return focused; 98261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 98361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return null; 98461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 98561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 98661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }; 98761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 98899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas final boolean isHeadersDataReady() { 98969381509eace8e71ba4886e9e1e78cda62b66516Dake Gu return mAdapter != null && mAdapter.size() != 0; 99069381509eace8e71ba4886e9e1e78cda62b66516Dake Gu } 99169381509eace8e71ba4886e9e1e78cda62b66516Dake Gu 99261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private final BrowseFrameLayout.OnChildFocusListener mOnChildFocusListener = 99361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu new BrowseFrameLayout.OnChildFocusListener() { 99461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 99561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 99661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { 99728fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu if (getChildFragmentManager().isDestroyed()) { 99828fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu return true; 99928fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu } 100061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu // Make sure not changing focus when requestFocus() is called. 100161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mCanShowHeaders && mShowingHeaders) { 10027fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout if (mHeadersSupportFragment != null && mHeadersSupportFragment.getView() != null && 10037fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout mHeadersSupportFragment.getView().requestFocus(direction, previouslyFocusedRect)) { 100461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return true; 100561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 100661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 10071c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata if (mMainFragment != null && mMainFragment.getView() != null && 10081c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragment.getView().requestFocus(direction, previouslyFocusedRect)) { 100961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return true; 101061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 1011e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout if (getTitleView() != null && 1012e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout getTitleView().requestFocus(direction, previouslyFocusedRect)) { 10137fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout return true; 10147fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout } 10157fd35190a1f0fd92f1275324b23708b5a2087a76Craig Stout return false; 10161c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 101761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 101861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 101961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onRequestChildFocus(View child, View focused) { 102028fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu if (getChildFragmentManager().isDestroyed()) { 102128fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu return; 102228fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu } 102361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (!mCanShowHeaders || isInHeadersTransition()) return; 102428fe4119471dcc0ccd752c331d6420fcf363f5a5Dake Gu int childId = child.getId(); 102561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (childId == R.id.browse_container_dock && mShowingHeaders) { 102661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu startHeadersTransitionInternal(false); 102761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else if (childId == R.id.browse_headers_dock && !mShowingHeaders) { 102861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu startHeadersTransitionInternal(true); 102961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 103061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 103161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }; 103261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 103361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 103461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onSaveInstanceState(Bundle outState) { 1035e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout super.onSaveInstanceState(outState); 1036fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak outState.putInt(CURRENT_SELECTED_POSITION, mSelectedPosition); 1037fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak outState.putBoolean(IS_PAGE_ROW, mIsPageRow); 1038fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 103961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mBackStackChangedListener != null) { 104061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBackStackChangedListener.save(outState); 104161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 104261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu outState.putBoolean(HEADER_SHOW, mShowingHeaders); 104361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 104461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 104561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 104661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 104761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onCreate(Bundle savedInstanceState) { 104861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onCreate(savedInstanceState); 104961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu TypedArray ta = getActivity().obtainStyledAttributes(R.styleable.LeanbackTheme); 10508e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing mContainerListMarginStart = (int) ta.getDimension( 105146443cb5b092f1d9156342645088eead9da026f6Dake Gu R.styleable.LeanbackTheme_browseRowsMarginStart, getActivity().getResources() 105246443cb5b092f1d9156342645088eead9da026f6Dake Gu .getDimensionPixelSize(R.dimen.lb_browse_rows_margin_start)); 105361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mContainerListAlignTop = (int) ta.getDimension( 105446443cb5b092f1d9156342645088eead9da026f6Dake Gu R.styleable.LeanbackTheme_browseRowsMarginTop, getActivity().getResources() 105546443cb5b092f1d9156342645088eead9da026f6Dake Gu .getDimensionPixelSize(R.dimen.lb_browse_rows_margin_top)); 105661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu ta.recycle(); 105761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 105861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu readArguments(getArguments()); 105961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 106034f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout if (mCanShowHeaders) { 106134f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout if (mHeadersBackStackEnabled) { 106234f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout mWithHeadersBackStackName = LB_HEADERS_BACKSTACK + this; 106334f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout mBackStackChangedListener = new BackStackListener(); 106434f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout getFragmentManager().addOnBackStackChangedListener(mBackStackChangedListener); 106534f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout mBackStackChangedListener.load(savedInstanceState); 106634f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout } else { 106734f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout if (savedInstanceState != null) { 106834f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout mShowingHeaders = savedInstanceState.getBoolean(HEADER_SHOW); 106934f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout } 107034f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout } 107134f3ee7e818a20939ef49abf5509bcfaea5c3db0Craig Stout } 1072a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1073f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata mScaleFactor = getResources().getFraction(R.fraction.lb_browse_rows_scale, 1, 1); 107461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 107561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 107661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 1077fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak public void onDestroyView() { 1078fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentRowsAdapter = null; 1079fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentAdapter = null; 1080fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragment = null; 1081fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mHeadersSupportFragment = null; 1082fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak super.onDestroyView(); 1083fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 1084fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 1085fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak @Override 108661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onDestroy() { 108761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mBackStackChangedListener != null) { 108861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu getFragmentManager().removeOnBackStackChangedListener(mBackStackChangedListener); 108961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 109061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onDestroy(); 109161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 109261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 109361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 109461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public View onCreateView(LayoutInflater inflater, ViewGroup container, 109561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu Bundle savedInstanceState) { 10967350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 1097a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata if (getChildFragmentManager().findFragmentById(R.id.scale_frame) == null) { 109861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment = new HeadersSupportFragment(); 1099bb0a680c10b84b83833a59634373140f8bd0750csusnata 1100a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata createMainFragment(mAdapter, mSelectedPosition); 1101bb0a680c10b84b83833a59634373140f8bd0750csusnata FragmentTransaction ft = getChildFragmentManager().beginTransaction() 1102bb0a680c10b84b83833a59634373140f8bd0750csusnata .replace(R.id.browse_headers_dock, mHeadersSupportFragment); 1103bb0a680c10b84b83833a59634373140f8bd0750csusnata 1104bb0a680c10b84b83833a59634373140f8bd0750csusnata if (mMainFragment != null) { 1105bb0a680c10b84b83833a59634373140f8bd0750csusnata ft.replace(R.id.scale_frame, mMainFragment); 1106bb0a680c10b84b83833a59634373140f8bd0750csusnata } else { 1107bb0a680c10b84b83833a59634373140f8bd0750csusnata // Empty adapter used to guard against lazy adapter loading. When this 1108bb0a680c10b84b83833a59634373140f8bd0750csusnata // fragment is instantiated, mAdapter might not have the data or might not 1109bb0a680c10b84b83833a59634373140f8bd0750csusnata // have been set. In either of those cases mFragmentAdapter will be null. 1110bb0a680c10b84b83833a59634373140f8bd0750csusnata // This way we can maintain the invariant that mMainFragmentAdapter is never 1111bb0a680c10b84b83833a59634373140f8bd0750csusnata // null and it avoids doing null checks all over the code. 1112bb0a680c10b84b83833a59634373140f8bd0750csusnata mMainFragmentAdapter = new MainFragmentAdapter(null); 1113cabb8eca86d0248274f57008ff66427fec2e927csusnata mMainFragmentAdapter.setFragmentHost(new FragmentHostImpl()); 1114bb0a680c10b84b83833a59634373140f8bd0750csusnata } 1115bb0a680c10b84b83833a59634373140f8bd0750csusnata 1116bb0a680c10b84b83833a59634373140f8bd0750csusnata ft.commit(); 111761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } else { 111861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment = (HeadersSupportFragment) getChildFragmentManager() 1119fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak .findFragmentById(R.id.browse_headers_dock); 1120fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragment = getChildFragmentManager().findFragmentById(R.id.scale_frame); 1121d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata mMainFragmentAdapter = ((MainFragmentAdapterProvider)mMainFragment) 1122d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata .getMainFragmentAdapter(); 1123dc1492d3655550b7a9c861aae1bd538410c7324dDake Gu mMainFragmentAdapter.setFragmentHost(new FragmentHostImpl()); 1124fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 1125fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mIsPageRow = savedInstanceState != null ? 1126fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak savedInstanceState.getBoolean(IS_PAGE_ROW, false) : false; 1127fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak 1128fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mSelectedPosition = savedInstanceState != null ? 1129fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak savedInstanceState.getInt(CURRENT_SELECTED_POSITION, 0) : 0; 11307350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 1131fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (!mIsPageRow) { 1132d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata if (mMainFragment instanceof MainFragmentRowsAdapterProvider) { 1133d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata mMainFragmentRowsAdapter = ((MainFragmentRowsAdapterProvider) mMainFragment) 1134d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata .getMainFragmentRowsAdapter(); 1135d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } else { 1136d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata mMainFragmentRowsAdapter = null; 1137d78de5e10e8426beff2ec22a3e3e0967a6b3d557susnata } 1138fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } else { 1139fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentRowsAdapter = null; 1140fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak } 114161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 114261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 114361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders); 114461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mHeaderPresenterSelector != null) { 114561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector); 114661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 114761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setAdapter(mAdapter); 11488df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu mHeadersSupportFragment.setOnHeaderViewSelectedListener(mHeaderViewSelectedListener); 114961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setOnHeaderClickedListener(mHeaderClickedListener); 11502f5ebf3f6f7bb6a24856f389e369b247118ba119susnata 115161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu View root = inflater.inflate(R.layout.lb_browse_fragment, container, false); 115261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1153684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata getProgressBarManager().setRootView((ViewGroup)root); 1154684f4a94f6f55b2abc5ed2677dfdfc9501dd6407susnata 115561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame); 115661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrowseFrame.setOnChildFocusListener(mOnChildFocusListener); 1157e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener); 115861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1159a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu installTitleView(inflater, mBrowseFrame, savedInstanceState); 1160a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 1161a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mScaleFrameLayout = (ScaleFrameLayout) root.findViewById(R.id.scale_frame); 1162a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mScaleFrameLayout.setPivotX(0); 1163a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mScaleFrameLayout.setPivotY(mContainerListAlignTop); 1164a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1165a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata setupMainFragment(); 1166a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 116761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mBrandColorSet) { 116861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setBackgroundColor(mBrandColor); 116961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 117061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11718403619efebe94666c0615c3fc85080a303acf80Dake Gu mSceneWithHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() { 117261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 117361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void run() { 117461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu showHeaders(true); 117561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 117661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }); 11778403619efebe94666c0615c3fc85080a303acf80Dake Gu mSceneWithoutHeaders = TransitionHelper.createScene(mBrowseFrame, new Runnable() { 117861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 117961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void run() { 118061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu showHeaders(false); 118161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 118261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }); 11838403619efebe94666c0615c3fc85080a303acf80Dake Gu mSceneAfterEntranceTransition = TransitionHelper.createScene(mBrowseFrame, new Runnable() { 1184c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu @Override 1185c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu public void run() { 1186c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setEntranceTransitionEndState(); 1187c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1188c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu }); 1189d0fc2e48059f718676a531af06a31849f54c1ca9susnata 119061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return root; 119161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 119261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 11931c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata private void setupMainFragment() { 1194fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (mMainFragmentRowsAdapter != null) { 119535d7a6c31606ed4ca38deda3cacae080a95c95c9susnata if (mAdapter != null) { 119635d7a6c31606ed4ca38deda3cacae080a95c95c9susnata mMainFragmentRowsAdapter.setAdapter(new ListRowDataAdapter(mAdapter)); 119735d7a6c31606ed4ca38deda3cacae080a95c95c9susnata } 11983eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu mMainFragmentRowsAdapter.setOnItemViewSelectedListener( 11993eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu new MainFragmentItemViewSelectedListener(mMainFragmentRowsAdapter)); 1200fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentRowsAdapter.setOnItemViewClickedListener(mOnItemViewClickedListener); 1201a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 12021c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 12031c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 1204a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu @Override 1205a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu boolean isReadyForPrepareEntranceTransition() { 1206cabb8eca86d0248274f57008ff66427fec2e927csusnata return mMainFragment != null && mMainFragment.getView() != null; 1207a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 1208a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 1209a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu @Override 1210a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu boolean isReadyForStartEntranceTransition() { 1211a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu return mMainFragment != null && mMainFragment.getView() != null 1212a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu && (!mIsPageRow || mMainFragmentAdapter.mFragmentHost.mDataReady); 1213a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu } 1214a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu 121599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void createHeadersTransition() { 12168403619efebe94666c0615c3fc85080a303acf80Dake Gu mHeadersTransition = TransitionHelper.loadTransition(getActivity(), 12174735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu mShowingHeaders ? 12184735bfcd924fec2d694523f34fac5f8151257dc7Dake Gu R.transition.lb_browse_headers_in : R.transition.lb_browse_headers_out); 121961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 12208403619efebe94666c0615c3fc85080a303acf80Dake Gu TransitionHelper.addTransitionListener(mHeadersTransition, new TransitionListener() { 122161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 122261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onTransitionStart(Object transition) { 122361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 122461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 122561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onTransitionEnd(Object transition) { 122661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersTransition = null; 122754bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu if (mMainFragmentAdapter != null) { 122854bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu mMainFragmentAdapter.onTransitionEnd(); 122954bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu if (!mShowingHeaders && mMainFragment != null) { 123054bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu View mainFragmentView = mMainFragment.getView(); 123154bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu if (mainFragmentView != null && !mainFragmentView.hasFocus()) { 123254bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu mainFragmentView.requestFocus(); 123354bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu } 123461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 123554bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu } 123654bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu if (mHeadersSupportFragment != null) { 123754bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu mHeadersSupportFragment.onTransitionEnd(); 123854bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu if (mShowingHeaders) { 123954bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu VerticalGridView headerGridView = mHeadersSupportFragment.getVerticalGridView(); 124054bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu if (headerGridView != null && !headerGridView.hasFocus()) { 124154bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu headerGridView.requestFocus(); 124254bab13ae9de4dd00002792bebf9531ede3c12e2Dake Gu } 124361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 1244d0fc2e48059f718676a531af06a31849f54c1ca9susnata } 12456fd4441435b14669deced90a05097dd5fe459acesusnata 12467350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata // Animate TitleView once header animation is complete. 12478ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu updateTitleViewVisibility(); 1248d0fc2e48059f718676a531af06a31849f54c1ca9susnata 124961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mBrowseTransitionListener != null) { 125061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mBrowseTransitionListener.onHeadersTransitionStop(mShowingHeaders); 125161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 125261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 125361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }); 125461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 125561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 12568ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu void updateTitleViewVisibility() { 12578ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (!mShowingHeaders) { 12588ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu boolean showTitleView; 12598ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (mIsPageRow && mMainFragmentAdapter != null) { 12608ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu // page fragment case: 12618ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showTitleView = mMainFragmentAdapter.mFragmentHost.mShowTitleView; 12628ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else { 12638ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu // regular row view case: 12648ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showTitleView = isFirstRowWithContent(mSelectedPosition); 12658ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12668ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (showTitleView) { 1267a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu showTitle(TitleViewAdapter.FULL_VIEW_VISIBLE); 12688ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else { 12698ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showTitle(false); 12708ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12718ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else { 12728ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu // when HeaderFragment is showing, showBranding and showSearch are slightly different 12738ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu boolean showBranding; 12748ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu boolean showSearch; 12758ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (mIsPageRow && mMainFragmentAdapter != null) { 12768ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showBranding = mMainFragmentAdapter.mFragmentHost.mShowTitleView; 12778ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else { 12788ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showBranding = isFirstRowWithContent(mSelectedPosition); 12798ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12808ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showSearch = isFirstRowWithContentOrPageRow(mSelectedPosition); 12818ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu int flags = 0; 1282a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu if (showBranding) flags |= TitleViewAdapter.BRANDING_VIEW_VISIBLE; 1283a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu if (showSearch) flags |= TitleViewAdapter.SEARCH_VIEW_VISIBLE; 12848ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (flags != 0) { 12858ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showTitle(flags); 12868ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } else { 12878ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu showTitle(false); 12888ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12898ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12908ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12918ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu 12928ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu boolean isFirstRowWithContentOrPageRow(int rowPosition) { 12938ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (mAdapter == null || mAdapter.size() == 0) { 12948ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return true; 12958ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 12968ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu for (int i = 0; i < mAdapter.size(); i++) { 12978ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu final Row row = (Row) mAdapter.get(i); 12988ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (row.isRenderedAsRowView() || row instanceof PageRow) { 12998ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return rowPosition == i; 13008ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13018ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13028ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return true; 13038ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13048ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu 13058ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu boolean isFirstRowWithContent(int rowPosition) { 13068ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (mAdapter == null || mAdapter.size() == 0) { 13078ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return true; 13088ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13098ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu for (int i = 0; i < mAdapter.size(); i++) { 13108ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu final Row row = (Row) mAdapter.get(i); 13118ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu if (row.isRenderedAsRowView()) { 13128ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return rowPosition == i; 13138ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13148ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13158ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu return true; 13168ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu } 13178ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu 131861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 131961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets the {@link PresenterSelector} used to render the row headers. 132061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 132161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param headerPresenterSelector The PresenterSelector that will determine 132261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the Presenter for each row header. 132361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 132461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setHeaderPresenterSelector(PresenterSelector headerPresenterSelector) { 132561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeaderPresenterSelector = headerPresenterSelector; 132661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mHeadersSupportFragment != null) { 132761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setPresenterSelector(mHeaderPresenterSelector); 132861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 132961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 133061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1331c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu private void setHeadersOnScreen(boolean onScreen) { 1332c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu MarginLayoutParams lp; 1333c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu View containerList; 133461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu containerList = mHeadersSupportFragment.getView(); 133561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu lp = (MarginLayoutParams) containerList.getLayoutParams(); 13368e3566285de4ac771d6188f62fe947e23d371a3dKris Giesing lp.setMarginStart(onScreen ? 0 : -mContainerListMarginStart); 133761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu containerList.setLayoutParams(lp); 1338c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 133961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 134099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void showHeaders(boolean show) { 1341c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu if (DEBUG) Log.v(TAG, "showHeaders " + show); 1342c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu mHeadersSupportFragment.setHeadersEnabled(show); 1343c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setHeadersOnScreen(show); 1344a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata expandMainFragment(!show); 1345a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1346a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1347a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private void expandMainFragment(boolean expand) { 1348a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata MarginLayoutParams params = (MarginLayoutParams) mScaleFrameLayout.getLayoutParams(); 1349c1ec7d7eff002329b245a4edb1b87da2f3b5e006Dake Gu params.setMarginStart(!expand ? mContainerListMarginStart : 0); 1350a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mScaleFrameLayout.setLayoutParams(params); 1351a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mMainFragmentAdapter.setExpand(expand); 1352a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1353a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata setMainFragmentAlignment(); 1354f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata final float scaleFactor = !expand 1355bb0a680c10b84b83833a59634373140f8bd0750csusnata && mMainFragmentScaleEnabled 1356bb0a680c10b84b83833a59634373140f8bd0750csusnata && mMainFragmentAdapter.isScalingEnabled() ? mScaleFactor : 1; 1357a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mScaleFrameLayout.setLayoutScaleY(scaleFactor); 1358a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mScaleFrameLayout.setChildScale(scaleFactor); 135961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 136061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 136161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private HeadersSupportFragment.OnHeaderClickedListener mHeaderClickedListener = 136261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu new HeadersSupportFragment.OnHeaderClickedListener() { 136361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 1364729cbf4cd57c87bcd569db5974c8cbd51a942581Dake Gu public void onHeaderClicked(RowHeaderPresenter.ViewHolder viewHolder, Row row) { 136561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (!mCanShowHeaders || !mShowingHeaders || isInHeadersTransition()) { 136661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 136761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 136861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu startHeadersTransitionInternal(false); 13691c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragment.getView().requestFocus(); 137061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 137161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }; 137261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 13733eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu class MainFragmentItemViewSelectedListener implements OnItemViewSelectedListener { 13743eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu MainFragmentRowsAdapter mMainFragmentRowsAdapter; 13753eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu 13763eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu public MainFragmentItemViewSelectedListener(MainFragmentRowsAdapter fragmentRowsAdapter) { 13773eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu mMainFragmentRowsAdapter = fragmentRowsAdapter; 13783eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu } 13793eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu 138061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 138161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, 138261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu RowPresenter.ViewHolder rowViewHolder, Row row) { 13833eb709dbe85f06b69cf1b683a2c1fe7109a85a9aDake Gu int position = mMainFragmentRowsAdapter.getSelectedPosition(); 138461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "row selected position " + position); 138561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu onRowSelected(position); 138661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mExternalOnItemViewSelectedListener != null) { 138761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mExternalOnItemViewSelectedListener.onItemSelected(itemViewHolder, item, 138861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu rowViewHolder, row); 138961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 139061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 139161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }; 139261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 13938df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu private HeadersSupportFragment.OnHeaderViewSelectedListener mHeaderViewSelectedListener = 13948df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu new HeadersSupportFragment.OnHeaderViewSelectedListener() { 139561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 13968df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu public void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row) { 13970d841b3454f896da58deb506ca22730bfd04f34fDake Gu int position = mHeadersSupportFragment.getSelectedPosition(); 139861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "header selected position " + position); 139961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu onRowSelected(position); 140061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 140161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu }; 140261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 140399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void onRowSelected(int position) { 140461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (position != mSelectedPosition) { 1405aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mSetSelectionRunnable.post( 1406aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout position, SetSelectionRunnable.TYPE_INTERNAL_SYNC, true); 140761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 140861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 140961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 141099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void setSelection(int position, boolean smooth) { 14111c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata if (position == NO_POSITION) { 14121c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata return; 141361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 14141c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 14151c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mHeadersSupportFragment.setSelectedPosition(position, smooth); 1416bb0a680c10b84b83833a59634373140f8bd0750csusnata replaceMainFragment(position); 1417bb0a680c10b84b83833a59634373140f8bd0750csusnata 1418bb0a680c10b84b83833a59634373140f8bd0750csusnata if (mMainFragmentRowsAdapter != null) { 1419bb0a680c10b84b83833a59634373140f8bd0750csusnata mMainFragmentRowsAdapter.setSelectedPosition(position, smooth); 1420bb0a680c10b84b83833a59634373140f8bd0750csusnata } 1421bb0a680c10b84b83833a59634373140f8bd0750csusnata mSelectedPosition = position; 14227350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 14238ff4c54cdaf5e8164fba7eac999c1ceafc462fc8Dake Gu updateTitleViewVisibility(); 1424bb0a680c10b84b83833a59634373140f8bd0750csusnata } 14253faa5780307cf10ff0e4a1d89a9ba099cdad2e15susnata 1426bb0a680c10b84b83833a59634373140f8bd0750csusnata private void replaceMainFragment(int position) { 1427a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata if (createMainFragment(mAdapter, position)) { 1428041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu swapToMainFragment(); 1429a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata expandMainFragment(!(mCanShowHeaders && mShowingHeaders)); 14301c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata setupMainFragment(); 1431a471ba40d52cde2d5a0afeded68c9d915f76183bDake Gu performPendingStates(); 14321c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 143361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 143461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1435041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu private void swapToMainFragment() { 1436041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu final VerticalGridView gridView = mHeadersSupportFragment.getVerticalGridView(); 14373f19c1616ed2749a70ecc764dccb467ec96aa1f4Dake Gu if (isShowingHeaders() && gridView != null 14383f19c1616ed2749a70ecc764dccb467ec96aa1f4Dake Gu && gridView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) { 1439041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu // if user is scrolling HeadersSupportFragment, swap to empty fragment and wait scrolling 1440041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu // finishes. 1441041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu getChildFragmentManager().beginTransaction() 1442041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu .replace(R.id.scale_frame, new Fragment()).commit(); 1443041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu gridView.addOnScrollListener(new RecyclerView.OnScrollListener() { 1444041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu @Override 1445041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 1446041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu if (newState == RecyclerView.SCROLL_STATE_IDLE) { 1447041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu gridView.removeOnScrollListener(this); 1448041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu FragmentManager fm = getChildFragmentManager(); 1449041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu Fragment currentFragment = fm.findFragmentById(R.id.scale_frame); 1450041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu if (currentFragment != mMainFragment) { 1451041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu fm.beginTransaction().replace(R.id.scale_frame, mMainFragment).commit(); 1452041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu } 1453041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu } 1454041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu } 1455041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu }); 1456041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu } else { 1457041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu // Otherwise swap immediately 1458041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu getChildFragmentManager().beginTransaction() 1459041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu .replace(R.id.scale_frame, mMainFragment).commit(); 1460041a037dbeb68c17322e62e729ec5ece6c7f5b20Dake Gu } 14611c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata } 14621c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 14633f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 14643f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Sets the selected row position with smooth animation. 14653f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 14663f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public void setSelectedPosition(int position) { 14673f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu setSelectedPosition(position, true); 14683f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 14693f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 14703f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu /** 14710d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * Gets position of currently selected row. 14720d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * @return Position of currently selected row. 14730d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu */ 14740d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu public int getSelectedPosition() { 14750d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu return mSelectedPosition; 14760d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu } 14770d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu 14780d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu /** 14793f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu * Sets the selected row position. 14803f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu */ 14813f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public void setSelectedPosition(int position, boolean smooth) { 1482aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout mSetSelectionRunnable.post( 1483aca6f4e4d28935fdc8f8d2a74cd41dc88c8b9e80Craig Stout position, SetSelectionRunnable.TYPE_USER_REQUEST, smooth); 14843f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu } 14853f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu 14860d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu /** 14870d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * Selects a Row and perform an optional task on the Row. For example 14880d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * <code>setSelectedPosition(10, true, new ListRowPresenterSelectItemViewHolderTask(5))</code> 14890d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * scrolls to 11th row and selects 6th item on that row. The method will be ignored if 14900d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * RowsSupportFragment has not been created (i.e. before {@link #onCreateView(LayoutInflater, 14910d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * ViewGroup, Bundle)}). 14920d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * 14930d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * @param rowPosition Which row to select. 14940d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * @param smooth True to scroll to the row, false for no animation. 14950d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * @param rowHolderTask Optional task to perform on the Row. When the task is not null, headers 14960d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu * fragment will be collapsed. 14970d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu */ 14980d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu public void setSelectedPosition(int rowPosition, boolean smooth, 1499cff6e470de4a0b2ed1dec944bdc848bd26f852f6Dake Gu final Presenter.ViewHolderTask rowHolderTask) { 1500fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (mMainFragmentAdapterRegistry == null) { 15010d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu return; 15020d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu } 15030d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu if (rowHolderTask != null) { 15040d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu startHeadersTransition(false); 15050d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu } 1506fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak if (mMainFragmentRowsAdapter != null) { 1507fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mMainFragmentRowsAdapter.setSelectedPosition(rowPosition, smooth, rowHolderTask); 1508a9cab85f79e3993c3d7c4f5e0246f8492bcc2a48susnata } 15090d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu } 15100d73d42df7cf4b325b8f49660e3326204915ce8fDake Gu 151161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu @Override 151261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void onStart() { 151361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu super.onStart(); 15142f5ebf3f6f7bb6a24856f389e369b247118ba119susnata mHeadersSupportFragment.setAlignment(mContainerListAlignTop); 1515a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata setMainFragmentAlignment(); 151661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 151761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mCanShowHeaders && mShowingHeaders && mHeadersSupportFragment.getView() != null) { 151861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.getView().requestFocus(); 1519b3756c53c5be55e8c8a2f6e2cda264407be84881susnata } else if ((!mCanShowHeaders || !mShowingHeaders) && mMainFragment.getView() != null) { 15201c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragment.getView().requestFocus(); 152161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 15221c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 152361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mCanShowHeaders) { 152461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu showHeaders(mShowingHeaders); 152561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 15261c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata 15273f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu if (isEntranceTransitionEnabled()) { 1528c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setEntranceTransitionStartState(); 1529c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 153061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 153161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 1532a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private void onExpandTransitionStart(boolean expand, final Runnable callback) { 1533a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata if (expand) { 1534a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata callback.run(); 1535a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata return; 1536a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1537a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata // Run a "pre" layout when we go non-expand, in order to get the initial 1538a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata // positions of added rows. 1539fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak new ExpandPreLayout(callback, mMainFragmentAdapter, getView()).execute(); 1540a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1541a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1542a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private void setMainFragmentAlignment() { 1543a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata int alignOffset = mContainerListAlignTop; 1544f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata if (mMainFragmentScaleEnabled 1545f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata && mMainFragmentAdapter.isScalingEnabled() 1546f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata && mShowingHeaders) { 1547f7a4099b29d7739616dd9d7e466b48dfda4b32f2susnata alignOffset = (int) (alignOffset / mScaleFactor + 0.5f); 1548a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1549a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mMainFragmentAdapter.setAlignment(alignOffset); 1550a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1551a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 155261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 1553a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Enables/disables headers transition on back key support. This is enabled by 155461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * default. The BrowseSupportFragment will add a back stack entry when headers are 155561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * showing. Running a headers transition when the back key is pressed only 155661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * works when the headers state is {@link #HEADERS_ENABLED} or 155761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * {@link #HEADERS_HIDDEN}. 155861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * <p> 155961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * NOTE: If an Activity has its own onBackPressed() handling, you must 156061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * disable this feature. You may use {@link #startHeadersTransition(boolean)} 156161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * and {@link BrowseTransitionListener} in your own back stack handling. 156261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 156361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public final void setHeadersTransitionOnBackEnabled(boolean headersBackStackEnabled) { 156461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersBackStackEnabled = headersBackStackEnabled; 156561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 156661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 156761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 156861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns true if headers transition on back key support is enabled. 156961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 157061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public final boolean isHeadersTransitionOnBackEnabled() { 157161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mHeadersBackStackEnabled; 157261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 157361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 157461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu private void readArguments(Bundle args) { 157561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (args == null) { 157661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return; 157761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 157861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (args.containsKey(ARG_TITLE)) { 157961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setTitle(args.getString(ARG_TITLE)); 158061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 158161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (args.containsKey(ARG_HEADERS_STATE)) { 158261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu setHeadersState(args.getInt(ARG_HEADERS_STATE)); 158361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 158461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 158561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 158661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 158761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Sets the state for the headers column in the browse fragment. Must be one 158861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * of {@link #HEADERS_ENABLED}, {@link #HEADERS_HIDDEN}, or 158961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * {@link #HEADERS_DISABLED}. 159061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * 159161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * @param headersState The state of the headers for the browse fragment. 159261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 159361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public void setHeadersState(int headersState) { 159461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (headersState < HEADERS_ENABLED || headersState > HEADERS_DISABLED) { 159561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu throw new IllegalArgumentException("Invalid headers state: " + headersState); 159661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 159761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (DEBUG) Log.v(TAG, "setHeadersState " + headersState); 159861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 159961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (headersState != mHeadersState) { 160061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersState = headersState; 160161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu switch (headersState) { 160261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu case HEADERS_ENABLED: 160361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mCanShowHeaders = true; 160461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mShowingHeaders = true; 160561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu break; 160661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu case HEADERS_HIDDEN: 160761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mCanShowHeaders = true; 160861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mShowingHeaders = false; 160961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu break; 161061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu case HEADERS_DISABLED: 161161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mCanShowHeaders = false; 161261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mShowingHeaders = false; 161361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu break; 161461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu default: 161561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu Log.w(TAG, "Unknown headers state: " + headersState); 161661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu break; 161761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 161861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu if (mHeadersSupportFragment != null) { 161961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu mHeadersSupportFragment.setHeadersGone(!mCanShowHeaders); 162061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 162161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 162261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 162361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu 162461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu /** 162561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Returns the state of the headers column in the browse fragment. 162661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */ 162761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu public int getHeadersState() { 162861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu return mHeadersState; 162961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu } 1630c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 16313f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 16323f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected Object createEntranceTransition() { 16338403619efebe94666c0615c3fc85080a303acf80Dake Gu return TransitionHelper.loadTransition(getActivity(), 16343f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu R.transition.lb_browse_entrance_transition); 1635c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1636c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 16373f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 16383f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected void runEntranceTransition(Object entranceTransition) { 16398403619efebe94666c0615c3fc85080a303acf80Dake Gu TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition); 1640c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1641c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 16423f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 1643902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu protected void onEntranceTransitionPrepare() { 1644902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu mHeadersSupportFragment.onTransitionPrepare(); 1645a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu // setEntranceTransitionStartState() might be called when mMainFragment is null, 1646a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu // make sure it is called. 1647a5a85434f936023043f074fb86eaa6d48f7f6411Dake Gu mMainFragmentAdapter.setEntranceTransitionState(false); 16481c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragmentAdapter.onTransitionPrepare(); 1649902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu } 1650902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu 1651902e68c114f86e8002516ff3f0248b722b6c5711Dake Gu @Override 16523f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected void onEntranceTransitionStart() { 16533f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu mHeadersSupportFragment.onTransitionStart(); 16541c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragmentAdapter.onTransitionStart(); 1655c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1656c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 16573f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu @Override 16583f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu protected void onEntranceTransitionEnd() { 1659b082c7277cff057bdff19e411e345c3d6fea2e12susnata if (mMainFragmentAdapter != null) { 1660b082c7277cff057bdff19e411e345c3d6fea2e12susnata mMainFragmentAdapter.onTransitionEnd(); 1661b082c7277cff057bdff19e411e345c3d6fea2e12susnata } 1662b082c7277cff057bdff19e411e345c3d6fea2e12susnata 1663b082c7277cff057bdff19e411e345c3d6fea2e12susnata if (mHeadersSupportFragment != null) { 1664b082c7277cff057bdff19e411e345c3d6fea2e12susnata mHeadersSupportFragment.onTransitionEnd(); 1665b082c7277cff057bdff19e411e345c3d6fea2e12susnata } 1666c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1667c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 16683f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu void setSearchOrbViewOnScreen(boolean onScreen) { 1669a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu View searchOrbView = getTitleViewAdapter().getSearchAffordanceView(); 1670b92376f5be24ddee5c6cd7c23b7c7e8e5c2cda68susnata if (searchOrbView != null) { 1671b92376f5be24ddee5c6cd7c23b7c7e8e5c2cda68susnata MarginLayoutParams lp = (MarginLayoutParams) searchOrbView.getLayoutParams(); 1672b92376f5be24ddee5c6cd7c23b7c7e8e5c2cda68susnata lp.setMarginStart(onScreen ? 0 : -mContainerListMarginStart); 1673b92376f5be24ddee5c6cd7c23b7c7e8e5c2cda68susnata searchOrbView.setLayoutParams(lp); 1674b92376f5be24ddee5c6cd7c23b7c7e8e5c2cda68susnata } 1675c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1676c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 1677c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu void setEntranceTransitionStartState() { 1678c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setHeadersOnScreen(false); 1679c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setSearchOrbViewOnScreen(false); 16801c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragmentAdapter.setEntranceTransitionState(false); 1681c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1682c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu 1683c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu void setEntranceTransitionEndState() { 1684c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setHeadersOnScreen(mShowingHeaders); 1685c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu setSearchOrbViewOnScreen(true); 16861c3ce0fa10ec24e4edd5e5ea909b4d4357534b53susnata mMainFragmentAdapter.setEntranceTransitionState(true); 1687c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 1688a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1689dee82957d1100c2b65e6850769abd3ff00f1ec95Dake Gu private class ExpandPreLayout implements ViewTreeObserver.OnPreDrawListener { 1690a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1691a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private final View mView; 1692a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private final Runnable mCallback; 1693a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata private int mState; 1694fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak private MainFragmentAdapter mainFragmentAdapter; 1695a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1696a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata final static int STATE_INIT = 0; 1697a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata final static int STATE_FIRST_DRAW = 1; 1698a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata final static int STATE_SECOND_DRAW = 2; 1699a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1700fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak ExpandPreLayout(Runnable callback, MainFragmentAdapter adapter, View view) { 1701fb11ded6cfa3965883e68625e0c7e14b4b4fe0b3Susnata Basak mView = view; 1702a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mCallback = callback; 1703a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mainFragmentAdapter = adapter; 1704a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1705a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1706a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata void execute() { 1707a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mView.getViewTreeObserver().addOnPreDrawListener(this); 1708a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mainFragmentAdapter.setExpand(false); 17092dda16536f0cc543f52abf53b18d6c1327031142Dake Gu // always trigger onPreDraw even adapter setExpand() does nothing. 17102dda16536f0cc543f52abf53b18d6c1327031142Dake Gu mView.invalidate(); 1711a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mState = STATE_INIT; 1712a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1713a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata 1714a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata @Override 1715a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata public boolean onPreDraw() { 1716dee82957d1100c2b65e6850769abd3ff00f1ec95Dake Gu if (getView() == null || getActivity() == null) { 1717dee82957d1100c2b65e6850769abd3ff00f1ec95Dake Gu mView.getViewTreeObserver().removeOnPreDrawListener(this); 1718dee82957d1100c2b65e6850769abd3ff00f1ec95Dake Gu return true; 1719dee82957d1100c2b65e6850769abd3ff00f1ec95Dake Gu } 1720a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata if (mState == STATE_INIT) { 1721a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mainFragmentAdapter.setExpand(true); 17222dda16536f0cc543f52abf53b18d6c1327031142Dake Gu // always trigger onPreDraw even adapter setExpand() does nothing. 17232dda16536f0cc543f52abf53b18d6c1327031142Dake Gu mView.invalidate(); 1724a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mState = STATE_FIRST_DRAW; 1725a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } else if (mState == STATE_FIRST_DRAW) { 1726a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mCallback.run(); 1727a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mView.getViewTreeObserver().removeOnPreDrawListener(this); 1728a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata mState = STATE_SECOND_DRAW; 1729a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1730a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata return false; 1731a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 1732a9f6062bd2dd02b3de253b57c69302893bf1f2e3susnata } 173361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu} 1734