1ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/* 2ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Copyright (C) 2015 The Android Open Source Project 3ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * 4ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * in compliance with the License. You may obtain a copy of the License at 6ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * 7ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * http://www.apache.org/licenses/LICENSE-2.0 8ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * 9ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Unless required by applicable law or agreed to in writing, software distributed under the License 10ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * or implied. See the License for the specific language governing permissions and limitations under 12ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * the License. 13ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 14ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingpackage android.support.v17.leanback.app; 15ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 16ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.animation.Animator; 17ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.animation.AnimatorSet; 18ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.app.Activity; 19ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.app.Fragment; 20ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.app.FragmentManager; 2137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Guimport android.app.FragmentManager.BackStackEntry; 22ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.app.FragmentTransaction; 23ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.content.Context; 2442ae32908312e63b474963fef789017c75feae37Dake Guimport android.os.Build; 25ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.os.Bundle; 26ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.annotation.NonNull; 27ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.R; 2868d693985e85ee5eed18f78beaaadbfd9b8a4f13susnataimport android.support.v17.leanback.transition.TransitionHelper; 29ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.widget.GuidanceStylist; 30ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.widget.GuidanceStylist.Guidance; 31ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.widget.GuidedAction; 32be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport android.support.v17.leanback.widget.GuidedActionAdapter; 33be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport android.support.v17.leanback.widget.GuidedActionAdapterGroup; 34ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.widget.GuidedActionsStylist; 35be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport android.support.v17.leanback.widget.ViewHolderTask; 3637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Guimport android.support.v4.app.ActivityCompat; 37d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Guimport android.support.v7.widget.RecyclerView; 38ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.util.Log; 39ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.util.TypedValue; 40ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.ContextThemeWrapper; 4142ae32908312e63b474963fef789017c75feae37Dake Guimport android.view.Gravity; 42ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.LayoutInflater; 43ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.View; 44ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.ViewGroup; 4568d693985e85ee5eed18f78beaaadbfd9b8a4f13susnataimport android.widget.FrameLayout; 46d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Guimport android.widget.LinearLayout; 47ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 48ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport java.util.ArrayList; 49ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport java.util.List; 50ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 51ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/** 52ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * A GuidedStepFragment is used to guide the user through a decision or series of decisions. 53751fc58ffff0614288c610fbd0767969abb9365fKris Giesing * It is composed of a guidance view on the left and a view on the right containing a list of 54751fc58ffff0614288c610fbd0767969abb9365fKris Giesing * possible actions. 55ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 56ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <h3>Basic Usage</h3> 57ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 5842ae32908312e63b474963fef789017c75feae37Dake Gu * Clients of GuidedStepFragment must create a custom subclass to attach to their Activities. 59ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * This custom subclass provides the information necessary to construct the user interface and 60ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * respond to user actions. At a minimum, subclasses should override: 61ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <ul> 62ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link #onCreateGuidance}, to provide instructions to the user</li> 63ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link #onCreateActions}, to provide a set of {@link GuidedAction}s the user can take</li> 64ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link #onGuidedActionClicked}, to respond to those actions</li> 65ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * </ul> 66ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 6742ae32908312e63b474963fef789017c75feae37Dake Gu * Clients use following helper functions to add GuidedStepFragment to Activity or FragmentManager: 6842ae32908312e63b474963fef789017c75feae37Dake Gu * <ul> 6942ae32908312e63b474963fef789017c75feae37Dake Gu * <li>{@link #addAsRoot(Activity, GuidedStepFragment, int)}, to be called during Activity onCreate, 7042ae32908312e63b474963fef789017c75feae37Dake Gu * adds GuidedStepFragment as the first Fragment in activity.</li> 7142ae32908312e63b474963fef789017c75feae37Dake Gu * <li>{@link #add(FragmentManager, GuidedStepFragment)} or {@link #add(FragmentManager, 7242ae32908312e63b474963fef789017c75feae37Dake Gu * GuidedStepFragment, int)}, to add GuidedStepFragment on top of existing Fragments or 7342ae32908312e63b474963fef789017c75feae37Dake Gu * replacing existing GuidedStepFragment when moving forward to next step.</li> 74517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>{@link #finishGuidedStepFragments()} can either finish the activity or pop all 75517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * GuidedStepFragment from stack. 76517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>If app chooses not to use the helper function, it is the app's responsibility to call 77517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * {@link #setUiStyle(int)} to select fragment transition and remember the stack entry where it 78517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * need pops to. 7942ae32908312e63b474963fef789017c75feae37Dake Gu * </ul> 80ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <h3>Theming and Stylists</h3> 81ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 82ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedStepFragment delegates its visual styling to classes called stylists. The {@link 83ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidanceStylist} is responsible for the left guidance view, while the {@link 84ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedActionsStylist} is responsible for the right actions view. The stylists use theme 85ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * attributes to derive values associated with the presentation, such as colors, animations, etc. 86ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Most simple visual aspects of GuidanceStylist and GuidedActionsStylist can be customized 87ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * via theming; see their documentation for more information. 88ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 89ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedStepFragments must have access to an appropriate theme in order for the stylists to 90ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * function properly. Specifically, the fragment must receive {@link 91ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * android.support.v17.leanback.R.style#Theme_Leanback_GuidedStep}, or a theme whose parent is 92ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * is set to that theme. Themes can be provided in one of three ways: 93ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <ul> 94ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>The simplest way is to set the theme for the host Activity to the GuidedStep theme or a 95ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * theme that derives from it.</li> 96ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>If the Activity already has a theme and setting its parent theme is inconvenient, the 97ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * existing Activity theme can have an entry added for the attribute {@link 98ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme}. If present, 99ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * this theme will be used by GuidedStepFragment as an overlay to the Activity's theme.</li> 100ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>Finally, custom subclasses of GuidedStepFragment may provide a theme through the {@link 101ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * #onProvideTheme} method. This can be useful if a subclass is used across multiple 102ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Activities.</li> 103ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * </ul> 104ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 105ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * If the theme is provided in multiple ways, the onProvideTheme override has priority, followed by 106ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * the Activty's theme. (Themes whose parent theme is already set to the guided step theme do not 107ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * need to set the guidedStepTheme attribute; if set, it will be ignored.) 108ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 109ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * If themes do not provide enough customizability, the stylists themselves may be subclassed and 110ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * provided to the GuidedStepFragment through the {@link #onCreateGuidanceStylist} and {@link 111ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * #onCreateActionsStylist} methods. The stylists have simple hooks so that subclasses 112ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * may override layout files; subclasses may also have more complex logic to determine styling. 113ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 114ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <h3>Guided sequences</h3> 115ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 116ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedStepFragments can be grouped together to provide a guided sequence. GuidedStepFragments 117ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * grouped as a sequence use custom animations provided by {@link GuidanceStylist} and 118ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@link GuidedActionsStylist} (or subclasses) during transitions between steps. Clients 119ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * should use {@link #add} to place subsequent GuidedFragments onto the fragment stack so that 120ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * custom animations are properly configured. (Custom animations are triggered automatically when 121ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * the fragment stack is subsequently popped by any normal mechanism.) 122ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 123ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <i>Note: Currently GuidedStepFragments grouped in this way must all be defined programmatically, 124ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * rather than in XML. This restriction may be removed in the future.</i> 12542ae32908312e63b474963fef789017c75feae37Dake Gu * 126ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme 12742ae32908312e63b474963fef789017c75feae37Dake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepBackground 128d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeight 129d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeightTwoPanels 130d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackground 1317f43e18536eae40705d5c63830e9edb283f196adDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackgroundDark 132a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsElevation 133ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see GuidanceStylist 134ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see GuidanceStylist.Guidance 135ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see GuidedAction 136ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see GuidedActionsStylist 137ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 138be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gupublic class GuidedStepFragment extends Fragment implements GuidedActionAdapter.FocusListener { 139ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 140ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private static final String TAG_LEAN_BACK_ACTIONS_FRAGMENT = "leanBackGuidedStepFragment"; 141ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private static final String EXTRA_ACTION_SELECTED_INDEX = "selectedIndex"; 1429050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu private static final String EXTRA_ACTION_PREFIX = "action_"; 1439050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu private static final String EXTRA_BUTTON_ACTION_PREFIX = "buttonaction_"; 14442ae32908312e63b474963fef789017c75feae37Dake Gu 145517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu private static final String ENTRY_NAME_REPLACE = "GuidedStepDefault"; 14637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 14737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu private static final String ENTRY_NAME_ENTRANCE = "GuidedStepEntrance"; 14837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 149e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu private static final boolean IS_FRAMEWORK_FRAGMENT = true; 150e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu 15142ae32908312e63b474963fef789017c75feae37Dake Gu /** 152fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * Fragment argument name for UI style. The argument value is persisted in fragment state and 153fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * used to select fragment transition. The value is initially {@link #UI_STYLE_ENTRANCE} and 154fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * might be changed in one of the three helper functions: 15542ae32908312e63b474963fef789017c75feae37Dake Gu * <ul> 156fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * <li>{@link #addAsRoot(Activity, GuidedStepFragment, int)} sets to 157fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * {@link #UI_STYLE_ACTIVITY_ROOT}</li> 15842ae32908312e63b474963fef789017c75feae37Dake Gu * <li>{@link #add(FragmentManager, GuidedStepFragment)} or {@link #add(FragmentManager, 159fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * GuidedStepFragment, int)} sets it to {@link #UI_STYLE_REPLACE} if there is already a 160fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * GuidedStepFragment on stack.</li> 161fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * <li>{@link #finishGuidedStepFragments()} changes current GuidedStepFragment to 162fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * {@link #UI_STYLE_ENTRANCE} for the non activity case. This is a special case that changes 163fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * the transition settings after fragment has been created, in order to force current 164fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * GuidedStepFragment run a return transition of {@link #UI_STYLE_ENTRANCE}</li> 16542ae32908312e63b474963fef789017c75feae37Dake Gu * </ul> 16642ae32908312e63b474963fef789017c75feae37Dake Gu * <p> 16742ae32908312e63b474963fef789017c75feae37Dake Gu * Argument value can be either: 16842ae32908312e63b474963fef789017c75feae37Dake Gu * <ul> 169517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>{@link #UI_STYLE_REPLACE}</li> 17042ae32908312e63b474963fef789017c75feae37Dake Gu * <li>{@link #UI_STYLE_ENTRANCE}</li> 17142ae32908312e63b474963fef789017c75feae37Dake Gu * <li>{@link #UI_STYLE_ACTIVITY_ROOT}</li> 17242ae32908312e63b474963fef789017c75feae37Dake Gu * </ul> 17342ae32908312e63b474963fef789017c75feae37Dake Gu */ 17442ae32908312e63b474963fef789017c75feae37Dake Gu public static final String EXTRA_UI_STYLE = "uiStyle"; 17542ae32908312e63b474963fef789017c75feae37Dake Gu 17642ae32908312e63b474963fef789017c75feae37Dake Gu /** 177517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * This is the case that we use GuidedStepFragment to replace another existing 178517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * GuidedStepFragment when moving forward to next step. Default behavior of this style is: 17942ae32908312e63b474963fef789017c75feae37Dake Gu * <ul> 180517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>Enter transition slides in from END(right), exit transition same as 181517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * {@link #UI_STYLE_ENTRANCE}. 18242ae32908312e63b474963fef789017c75feae37Dake Gu * </li> 18342ae32908312e63b474963fef789017c75feae37Dake Gu * </ul> 18442ae32908312e63b474963fef789017c75feae37Dake Gu */ 185517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu public static final int UI_STYLE_REPLACE = 0; 18642ae32908312e63b474963fef789017c75feae37Dake Gu 18742ae32908312e63b474963fef789017c75feae37Dake Gu /** 188c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu * @deprecated Same value as {@link #UI_STYLE_REPLACE}. 189c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu */ 190c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu @Deprecated 191c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu public static final int UI_STYLE_DEFAULT = 0; 192c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu 193c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu /** 194517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Default value for argument {@link #EXTRA_UI_STYLE}. The default value is assigned in 195517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * GuidedStepFragment constructor. This is the case that we show GuidedStepFragment on top of 196517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * other content. The default behavior of this style: 19742ae32908312e63b474963fef789017c75feae37Dake Gu * <ul> 198517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>Enter transition slides in from two sides, exit transition slide out to START(left). 199517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Background will be faded in. Note: Changing exit transition by UI style is not working 200517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * because fragment transition asks for exit transition before UI style is restored in Fragment 20142ae32908312e63b474963fef789017c75feae37Dake Gu * .onCreate().</li> 20242ae32908312e63b474963fef789017c75feae37Dake Gu * </ul> 203fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * When popping multiple GuidedStepFragment, {@link #finishGuidedStepFragments()} also changes 204fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * the top GuidedStepFragment to UI_STYLE_ENTRANCE in order to run the return transition 205fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * (reverse of enter transition) of UI_STYLE_ENTRANCE. 20642ae32908312e63b474963fef789017c75feae37Dake Gu */ 20742ae32908312e63b474963fef789017c75feae37Dake Gu public static final int UI_STYLE_ENTRANCE = 1; 20842ae32908312e63b474963fef789017c75feae37Dake Gu 20942ae32908312e63b474963fef789017c75feae37Dake Gu /** 210517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * One possible value of argument {@link #EXTRA_UI_STYLE}. This is the case that we show first 211517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * GuidedStepFragment in a separate activity. The default behavior of this style: 21242ae32908312e63b474963fef789017c75feae37Dake Gu * <ul> 213517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>Enter transition is assigned null (will rely on activity transition), exit transition is 214517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * same as {@link #UI_STYLE_ENTRANCE}. Note: Changing exit transition by UI style is not working 215ce4c2014042fe6e4723bab30741039848adcf4beDake Gu * because fragment transition asks for exit transition before UI style is restored in 21642ae32908312e63b474963fef789017c75feae37Dake Gu * Fragment.onCreate().</li> 21742ae32908312e63b474963fef789017c75feae37Dake Gu * </ul> 21842ae32908312e63b474963fef789017c75feae37Dake Gu */ 21942ae32908312e63b474963fef789017c75feae37Dake Gu public static final int UI_STYLE_ACTIVITY_ROOT = 2; 22042ae32908312e63b474963fef789017c75feae37Dake Gu 221e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata /** 222e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * Animation to slide the contents from the side (left/right). 223e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * @hide 224e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata */ 225e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata public static final int SLIDE_FROM_SIDE = 0; 226e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata 227e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata /** 228e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * Animation to slide the contents from the bottom. 229e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * @hide 230e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata */ 231e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata public static final int SLIDE_FROM_BOTTOM = 1; 232e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata 233ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private static final String TAG = "GuidedStepFragment"; 23442ae32908312e63b474963fef789017c75feae37Dake Gu private static final boolean DEBUG = false; 235ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 236e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu /** 237e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu * @hide 238e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu */ 239e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu public static class DummyFragment extends Fragment { 240e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu @Override 241e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu public View onCreateView(LayoutInflater inflater, ViewGroup container, 242e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu Bundle savedInstanceState) { 243e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu final View v = new View(inflater.getContext()); 244e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu v.setVisibility(View.GONE); 245e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu return v; 246e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu } 247e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu } 248e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu 249ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private int mTheme; 25042ae32908312e63b474963fef789017c75feae37Dake Gu private ContextThemeWrapper mThemeWrapper; 251ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private GuidanceStylist mGuidanceStylist; 252ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private GuidedActionsStylist mActionsStylist; 253d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu private GuidedActionsStylist mButtonActionsStylist; 254ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private GuidedActionAdapter mAdapter; 255be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu private GuidedActionAdapter mSubAdapter; 256d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu private GuidedActionAdapter mButtonAdapter; 25743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu private GuidedActionAdapterGroup mAdapterGroup; 258ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private List<GuidedAction> mActions = new ArrayList<GuidedAction>(); 259d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu private List<GuidedAction> mButtonActions = new ArrayList<GuidedAction>(); 260ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private int mSelectedIndex = -1; 261d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu private int mButtonSelectedIndex = -1; 262e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata private int entranceTransitionType = SLIDE_FROM_SIDE; 263ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 264ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidedStepFragment() { 265ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // We need to supply the theme before any potential call to onInflate in order 266ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // for the defaulting to work properly. 267ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mTheme = onProvideTheme(); 268ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mGuidanceStylist = onCreateGuidanceStylist(); 269ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActionsStylist = onCreateActionsStylist(); 270d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActionsStylist = onCreateButtonActionsStylist(); 27142ae32908312e63b474963fef789017c75feae37Dake Gu onProvideFragmentTransitions(); 272ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 273ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 274ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 275ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Creates the presenter used to style the guidance panel. The default implementation returns 276ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * a basic GuidanceStylist. 277ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The GuidanceStylist used in this fragment. 278ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 279ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidanceStylist onCreateGuidanceStylist() { 280ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return new GuidanceStylist(); 281ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 282ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 283ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 284ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Creates the presenter used to style the guided actions panel. The default implementation 285ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * returns a basic GuidedActionsStylist. 286ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The GuidedActionsStylist used in this fragment. 287ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 288ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidedActionsStylist onCreateActionsStylist() { 289ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return new GuidedActionsStylist(); 290ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 291ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 292ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 293d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Creates the presenter used to style a sided actions panel for button only. 294d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * The default implementation returns a basic GuidedActionsStylist. 295d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return The GuidedActionsStylist used in this fragment. 296d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 297d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public GuidedActionsStylist onCreateButtonActionsStylist() { 298be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist stylist = new GuidedActionsStylist(); 299be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu stylist.setAsButtonActions(); 300be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu return stylist; 301d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 302d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 303d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 304ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the theme used for styling the fragment. The default returns -1, indicating that the 305ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * host Activity's theme should be used. 306ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The theme resource ID of the theme to use in this fragment, or -1 to use the 307ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * host Activity's theme. 308ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 309ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public int onProvideTheme() { 310ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return -1; 311ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 312ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 313ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 314ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the information required to provide guidance to the user. This hook is called during 315ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@link #onCreateView}. May be overridden to return a custom subclass of {@link 316ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidanceStylist.Guidance} for use in a subclass of {@link GuidanceStylist}. The default 317ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * returns a Guidance object with empty fields; subclasses should override. 318ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param savedInstanceState The saved instance state from onCreateView. 319ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The Guidance object representing the information used to guide the user. 320ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 321ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public @NonNull Guidance onCreateGuidance(Bundle savedInstanceState) { 322ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return new Guidance("", "", "", null); 323ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 324ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 325ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 326ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Fills out the set of actions available to the user. This hook is called during {@link 327ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * #onCreate}. The default leaves the list of actions empty; subclasses should override. 328ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param actions A non-null, empty list ready to be populated. 329ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param savedInstanceState The saved instance state from onCreate. 330ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 331ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) { 332ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 333ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 334ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 335d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Fills out the set of actions shown at right available to the user. This hook is called during 336d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * {@link #onCreate}. The default leaves the list of actions empty; subclasses may override. 337d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param actions A non-null, empty list ready to be populated. 338d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param savedInstanceState The saved instance state from onCreate. 339d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 340d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public void onCreateButtonActions(@NonNull List<GuidedAction> actions, 341d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu Bundle savedInstanceState) { 342d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 343d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 344d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 345ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Callback invoked when an action is taken by the user. Subclasses should override in 346ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * order to act on the user's decisions. 347ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param action The chosen action. 348ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 349ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onGuidedActionClicked(GuidedAction action) { 350ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 351ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 352ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 353be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * Callback invoked when an action in sub actions is taken by the user. Subclasses should 354be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * override in order to act on the user's decisions. Default return value is true to close 355be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * the sub actions list. 356be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @param action The chosen action. 357be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @return true to collapse the sub actions list, false to keep it expanded. 358be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu */ 359be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public boolean onSubGuidedActionClicked(GuidedAction action) { 360be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu return true; 361be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 362be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu 363be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu /** 364be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @return True if the sub actions list is expanded, false otherwise. 365be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu */ 366be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public boolean isSubActionsExpanded() { 367be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu return mActionsStylist.isSubActionsExpanded(); 368be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 369be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu 370be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu /** 371be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * Expand a given action's sub actions list. 372be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @param action GuidedAction to expand. 373be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @see GuidedAction#getSubActions() 374be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu */ 375be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void expandSubActions(GuidedAction action) { 376be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu final int actionPosition = mActions.indexOf(action); 377be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu if (actionPosition < 0) { 378be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu return; 379be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 380be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mActionsStylist.getActionsGridView().setSelectedPositionSmooth(actionPosition, 381be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu new ViewHolderTask() { 382be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu @Override 383be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void run(RecyclerView.ViewHolder vh) { 384be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder) vh; 385be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mActionsStylist.setExpandedViewHolder(avh); 386be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 387be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu }); 388be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 389be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu 390be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu /** 391be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * Collapse sub actions list. 392be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @see GuidedAction#getSubActions() 393be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu */ 394be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void collapseSubActions() { 395be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mActionsStylist.setExpandedViewHolder(null); 396be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 397be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu 398be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu /** 399ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Callback invoked when an action is focused (made to be the current selection) by the user. 400ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 401ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 402ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onGuidedActionFocused(GuidedAction action) { 403ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 404ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 405ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 406bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu * Callback invoked when an action's title or description has been edited, this happens either 407bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu * when user clicks confirm button in IME or user closes IME window by BACK key. 40816ab389e0bd11594059f8164a1477045ee625154Dake Gu * @deprecated Override {@link #onGuidedActionEditedAndProceed(GuidedAction)} and/or 40916ab389e0bd11594059f8164a1477045ee625154Dake Gu * {@link #onGuidedActionEditCanceled(GuidedAction)}. 4104158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing */ 41116ab389e0bd11594059f8164a1477045ee625154Dake Gu @Deprecated 4124158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing public void onGuidedActionEdited(GuidedAction action) { 4134158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 4144158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 4154158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing /** 41616ab389e0bd11594059f8164a1477045ee625154Dake Gu * Callback invoked when an action has been canceled editing, for example when user closes 41716ab389e0bd11594059f8164a1477045ee625154Dake Gu * IME window by BACK key. Default implementation calls deprecated method 41816ab389e0bd11594059f8164a1477045ee625154Dake Gu * {@link #onGuidedActionEdited(GuidedAction)}. 41916ab389e0bd11594059f8164a1477045ee625154Dake Gu * @param action The action which has been canceled editing. 42016ab389e0bd11594059f8164a1477045ee625154Dake Gu */ 42116ab389e0bd11594059f8164a1477045ee625154Dake Gu public void onGuidedActionEditCanceled(GuidedAction action) { 42216ab389e0bd11594059f8164a1477045ee625154Dake Gu onGuidedActionEdited(action); 42316ab389e0bd11594059f8164a1477045ee625154Dake Gu } 42416ab389e0bd11594059f8164a1477045ee625154Dake Gu 42516ab389e0bd11594059f8164a1477045ee625154Dake Gu /** 42616ab389e0bd11594059f8164a1477045ee625154Dake Gu * Callback invoked when an action has been edited, for example when user clicks confirm button 42716ab389e0bd11594059f8164a1477045ee625154Dake Gu * in IME window. Default implementation calls deprecated method 428bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu * {@link #onGuidedActionEdited(GuidedAction)} and returns {@link GuidedAction#ACTION_ID_NEXT}. 429c1741246af607f6be2389056da0182c40f938348Dake Gu * 430c1741246af607f6be2389056da0182c40f938348Dake Gu * @param action The action that has been edited. 431c1741246af607f6be2389056da0182c40f938348Dake Gu * @return ID of the action will be focused or {@link GuidedAction#ACTION_ID_NEXT}, 432c1741246af607f6be2389056da0182c40f938348Dake Gu * {@link GuidedAction#ACTION_ID_CURRENT}. 433c1741246af607f6be2389056da0182c40f938348Dake Gu */ 434c1741246af607f6be2389056da0182c40f938348Dake Gu public long onGuidedActionEditedAndProceed(GuidedAction action) { 435c1741246af607f6be2389056da0182c40f938348Dake Gu onGuidedActionEdited(action); 436c1741246af607f6be2389056da0182c40f938348Dake Gu return GuidedAction.ACTION_ID_NEXT; 437c1741246af607f6be2389056da0182c40f938348Dake Gu } 438c1741246af607f6be2389056da0182c40f938348Dake Gu 439c1741246af607f6be2389056da0182c40f938348Dake Gu /** 440ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Adds the specified GuidedStepFragment to the fragment stack, replacing any existing 44142ae32908312e63b474963fef789017c75feae37Dake Gu * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom 442bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu * transitions. A backstack entry is added, so the fragment will be dismissed when BACK key 443bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu * is pressed. 444517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_REPLACE} 44542ae32908312e63b474963fef789017c75feae37Dake Gu * <li>If current fragment on stack is not GuidedStepFragment: assign {@link #UI_STYLE_ENTRANCE} 446ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p> 447ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Note: currently fragments added using this method must be created programmatically rather 448ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * than via XML. 449ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param fragmentManager The FragmentManager to be used in the transaction. 450ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param fragment The GuidedStepFragment to be inserted into the fragment stack. 45168a94e5c24b85f071fb57727954510fff0224d9cDake Gu * @return The ID returned by the call FragmentTransaction.commit. 452ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 453ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public static int add(FragmentManager fragmentManager, GuidedStepFragment fragment) { 454ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return add(fragmentManager, fragment, android.R.id.content); 455ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 456ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 45742ae32908312e63b474963fef789017c75feae37Dake Gu /** 45842ae32908312e63b474963fef789017c75feae37Dake Gu * Adds the specified GuidedStepFragment to the fragment stack, replacing any existing 45942ae32908312e63b474963fef789017c75feae37Dake Gu * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom 460bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu * transitions. A backstack entry is added, so the fragment will be dismissed when BACK key 461bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu * is pressed. 462517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_REPLACE} and 4630b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * {@link #onAddSharedElementTransition(FragmentTransaction, GuidedStepFragment)} will be called 4640b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * to perform shared element transition between GuidedStepFragments. 46542ae32908312e63b474963fef789017c75feae37Dake Gu * <li>If current fragment on stack is not GuidedStepFragment: assign {@link #UI_STYLE_ENTRANCE} 46642ae32908312e63b474963fef789017c75feae37Dake Gu * <p> 46742ae32908312e63b474963fef789017c75feae37Dake Gu * Note: currently fragments added using this method must be created programmatically rather 46842ae32908312e63b474963fef789017c75feae37Dake Gu * than via XML. 46942ae32908312e63b474963fef789017c75feae37Dake Gu * @param fragmentManager The FragmentManager to be used in the transaction. 47042ae32908312e63b474963fef789017c75feae37Dake Gu * @param fragment The GuidedStepFragment to be inserted into the fragment stack. 47142ae32908312e63b474963fef789017c75feae37Dake Gu * @param id The id of container to add GuidedStepFragment, can be android.R.id.content. 47268a94e5c24b85f071fb57727954510fff0224d9cDake Gu * @return The ID returned by the call FragmentTransaction.commit. 47342ae32908312e63b474963fef789017c75feae37Dake Gu */ 47442ae32908312e63b474963fef789017c75feae37Dake Gu public static int add(FragmentManager fragmentManager, GuidedStepFragment fragment, int id) { 4750b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu GuidedStepFragment current = getCurrentGuidedStepFragment(fragmentManager); 4760b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu boolean inGuidedStep = current != null; 477e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu if (IS_FRAMEWORK_FRAGMENT && Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23 478e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu && !inGuidedStep) { 479e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu // workaround b/22631964 for framework fragment 480e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu fragmentManager.beginTransaction() 481e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu .replace(id, new DummyFragment(), TAG_LEAN_BACK_ACTIONS_FRAGMENT) 482e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu .commit(); 483e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu } 48442ae32908312e63b474963fef789017c75feae37Dake Gu FragmentTransaction ft = fragmentManager.beginTransaction(); 485ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 486517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu fragment.setUiStyle(inGuidedStep ? UI_STYLE_REPLACE : UI_STYLE_ENTRANCE); 48737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu ft.addToBackStack(fragment.generateStackEntryName()); 4880b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu if (current != null) { 4890b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu fragment.onAddSharedElementTransition(ft, current); 4900b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu } 49142ae32908312e63b474963fef789017c75feae37Dake Gu return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit(); 49242ae32908312e63b474963fef789017c75feae37Dake Gu } 49342ae32908312e63b474963fef789017c75feae37Dake Gu 49442ae32908312e63b474963fef789017c75feae37Dake Gu /** 495517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_REPLACE} (aka 496517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * when the GuidedStepFragment replacing an existing GuidedStepFragment). Default implementation 497517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * establishes connections between action background views to morph action background bounds 498517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * change from disappearing GuidedStepFragment into this GuidedStepFragment. The default 4990b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * implementation heavily relies on {@link GuidedActionsStylist}'s layout, app may override this 5000b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * method when modifying the default layout of {@link GuidedActionsStylist}. 501517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * 5020b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * @see GuidedActionsStylist 5030b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * @see #onProvideFragmentTransitions() 5040b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * @param ft The FragmentTransaction to add shared element. 5050b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * @param disappearing The disappearing fragment. 5060b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu */ 5070b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu protected void onAddSharedElementTransition(FragmentTransaction ft, GuidedStepFragment 5080b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu disappearing) { 5098bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri View fragmentView = disappearing.getView(); 5108bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5110b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu R.id.action_fragment_root), "action_fragment_root"); 5128bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5130b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu R.id.action_fragment_background), "action_fragment_background"); 5148bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5150b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu R.id.action_fragment), "action_fragment"); 5168bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5170b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu R.id.guidedactions_root), "guidedactions_root"); 5188bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5198e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu R.id.guidedactions_content), "guidedactions_content"); 5208bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5218e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu R.id.guidedactions_list_background), "guidedactions_list_background"); 5228bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5230b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu R.id.guidedactions_root2), "guidedactions_root2"); 5248bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5258e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu R.id.guidedactions_content2), "guidedactions_content2"); 5268bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri addNonNullSharedElementTransition(ft, fragmentView.findViewById( 5278e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu R.id.guidedactions_list_background2), "guidedactions_list_background2"); 5280b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu } 5290b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu 5308bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri private static void addNonNullSharedElementTransition (FragmentTransaction ft, View subView, 5318bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri String transitionName) 5328bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri { 5338bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri if (subView != null) 5348bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri TransitionHelper.addSharedElement(ft, subView, transitionName); 5358bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri } 5368bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri 5370b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu /** 53837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * Returns BackStackEntry name for the GuidedStepFragment or empty String if no entry is 53937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * associated. Note {@link #UI_STYLE_ACTIVITY_ROOT} will return empty String. The method 54037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * returns undefined value if the fragment is not in FragmentManager. 54137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @return BackStackEntry name for the GuidedStepFragment or empty String if no entry is 54237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * associated. 54337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu */ 544fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu String generateStackEntryName() { 54537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return generateStackEntryName(getUiStyle(), getClass()); 54637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 54737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 54837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu /** 54937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * Generates BackStackEntry name for GuidedStepFragment class or empty String if no entry is 55037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * associated. Note {@link #UI_STYLE_ACTIVITY_ROOT} is not allowed and returns empty String. 551517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @param uiStyle {@link #UI_STYLE_REPLACE} or {@link #UI_STYLE_ENTRANCE} 55237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @return BackStackEntry name for the GuidedStepFragment or empty String if no entry is 55337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * associated. 55437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu */ 555fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu static String generateStackEntryName(int uiStyle, Class guidedStepFragmentClass) { 55637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu if (!GuidedStepFragment.class.isAssignableFrom(guidedStepFragmentClass)) { 55737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return ""; 55837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 55937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu switch (uiStyle) { 560517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu case UI_STYLE_REPLACE: 561517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu return ENTRY_NAME_REPLACE + guidedStepFragmentClass.getName(); 56237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu case UI_STYLE_ENTRANCE: 56337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return ENTRY_NAME_ENTRANCE + guidedStepFragmentClass.getName(); 56437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu case UI_STYLE_ACTIVITY_ROOT: 56537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu default: 56637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return ""; 56737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 56837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 56937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 57037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu /** 571fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * Returns true if the backstack entry represents GuidedStepFragment with 572fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * {@link #UI_STYLE_ENTRANCE}, i.e. this is the first GuidedStepFragment pushed to stack; false 573fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * otherwise. 574fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu * @see #generateStackEntryName(int, Class) 57537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @param backStackEntryName Name of BackStackEntry. 57637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @return True if the backstack represents GuidedStepFragment with {@link #UI_STYLE_ENTRANCE}; 57737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * false otherwise. 57837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu */ 579fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu static boolean isStackEntryUiStyleEntrance(String backStackEntryName) { 58037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE); 58137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 58237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 58337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu /** 58437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * Extract Class name from BackStackEntry name. 58537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @param backStackEntryName Name of BackStackEntry. 58637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @return Class name of GuidedStepFragment. 58737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu */ 588fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu static String getGuidedStepFragmentClassName(String backStackEntryName) { 589517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu if (backStackEntryName.startsWith(ENTRY_NAME_REPLACE)) { 590517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu return backStackEntryName.substring(ENTRY_NAME_REPLACE.length()); 59137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } else if (backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE)) { 59237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return backStackEntryName.substring(ENTRY_NAME_ENTRANCE.length()); 59337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } else { 59437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return ""; 59537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 59637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 59737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 59837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu /** 599bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu * Adds the specified GuidedStepFragment as content of Activity; no backstack entry is added so 60068a94e5c24b85f071fb57727954510fff0224d9cDake Gu * the activity will be dismissed when BACK key is pressed. The method is typically called in 60168a94e5c24b85f071fb57727954510fff0224d9cDake Gu * Activity.onCreate() when savedInstanceState is null. When savedInstanceState is not null, 60268a94e5c24b85f071fb57727954510fff0224d9cDake Gu * the Activity is being restored, do not call addAsRoot() to duplicate the Fragment restored 60368a94e5c24b85f071fb57727954510fff0224d9cDake Gu * by FragmentManager. 60442ae32908312e63b474963fef789017c75feae37Dake Gu * {@link #UI_STYLE_ACTIVITY_ROOT} is assigned. 60542ae32908312e63b474963fef789017c75feae37Dake Gu * 60642ae32908312e63b474963fef789017c75feae37Dake Gu * Note: currently fragments added using this method must be created programmatically rather 60742ae32908312e63b474963fef789017c75feae37Dake Gu * than via XML. 60842ae32908312e63b474963fef789017c75feae37Dake Gu * @param activity The Activity to be used to insert GuidedstepFragment. 60942ae32908312e63b474963fef789017c75feae37Dake Gu * @param fragment The GuidedStepFragment to be inserted into the fragment stack. 61042ae32908312e63b474963fef789017c75feae37Dake Gu * @param id The id of container to add GuidedStepFragment, can be android.R.id.content. 61168a94e5c24b85f071fb57727954510fff0224d9cDake Gu * @return The ID returned by the call FragmentTransaction.commit, or -1 there is already 61268a94e5c24b85f071fb57727954510fff0224d9cDake Gu * GuidedStepFragment. 61342ae32908312e63b474963fef789017c75feae37Dake Gu */ 61442ae32908312e63b474963fef789017c75feae37Dake Gu public static int addAsRoot(Activity activity, GuidedStepFragment fragment, int id) { 61542ae32908312e63b474963fef789017c75feae37Dake Gu // Workaround b/23764120: call getDecorView() to force requestFeature of ActivityTransition. 61642ae32908312e63b474963fef789017c75feae37Dake Gu activity.getWindow().getDecorView(); 61742ae32908312e63b474963fef789017c75feae37Dake Gu FragmentManager fragmentManager = activity.getFragmentManager(); 61868a94e5c24b85f071fb57727954510fff0224d9cDake Gu if (fragmentManager.findFragmentByTag(TAG_LEAN_BACK_ACTIONS_FRAGMENT) != null) { 61968a94e5c24b85f071fb57727954510fff0224d9cDake Gu Log.w(TAG, "Fragment is already exists, likely calling " + 62068a94e5c24b85f071fb57727954510fff0224d9cDake Gu "addAsRoot() when savedInstanceState is not null in Activity.onCreate()."); 62168a94e5c24b85f071fb57727954510fff0224d9cDake Gu return -1; 62268a94e5c24b85f071fb57727954510fff0224d9cDake Gu } 62342ae32908312e63b474963fef789017c75feae37Dake Gu FragmentTransaction ft = fragmentManager.beginTransaction(); 62442ae32908312e63b474963fef789017c75feae37Dake Gu fragment.setUiStyle(UI_STYLE_ACTIVITY_ROOT); 62542ae32908312e63b474963fef789017c75feae37Dake Gu return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit(); 62642ae32908312e63b474963fef789017c75feae37Dake Gu } 62742ae32908312e63b474963fef789017c75feae37Dake Gu 628ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 629ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the current GuidedStepFragment on the fragment transaction stack. 630ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The current GuidedStepFragment, if any, on the fragment transaction stack. 631ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 632ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public static GuidedStepFragment getCurrentGuidedStepFragment(FragmentManager fm) { 633ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Fragment f = fm.findFragmentByTag(TAG_LEAN_BACK_ACTIONS_FRAGMENT); 634ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (f instanceof GuidedStepFragment) { 635ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return (GuidedStepFragment) f; 636ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 637ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return null; 638ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 639ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 640ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 641ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the GuidanceStylist that displays guidance information for the user. 642ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The GuidanceStylist for this fragment. 643ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 644ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidanceStylist getGuidanceStylist() { 645ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return mGuidanceStylist; 646ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 647ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 648ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 649ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the GuidedActionsStylist that displays the actions the user may take. 650ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The GuidedActionsStylist for this fragment. 651ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 652ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidedActionsStylist getGuidedActionsStylist() { 653ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return mActionsStylist; 654ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 655ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 656ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 657d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Returns the list of button GuidedActions that the user may take in this fragment. 658d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return The list of button GuidedActions for this fragment. 659d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 660d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public List<GuidedAction> getButtonActions() { 661d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return mButtonActions; 662d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 663d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 664d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 665d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Find button GuidedAction by Id. 666d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param id Id of the button action to search. 667d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return GuidedAction object or null if not found. 668d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 669d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public GuidedAction findButtonActionById(long id) { 670d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu int index = findButtonActionPositionById(id); 671d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return index >= 0 ? mButtonActions.get(index) : null; 672d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 673d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 674d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 675d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Find button GuidedAction position in array by Id. 676d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param id Id of the button action to search. 677d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return position of GuidedAction object in array or -1 if not found. 678d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 679d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public int findButtonActionPositionById(long id) { 680d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu if (mButtonActions != null) { 681d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu for (int i = 0; i < mButtonActions.size(); i++) { 682d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu GuidedAction action = mButtonActions.get(i); 683d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu if (mButtonActions.get(i).getId() == id) { 684d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return i; 685d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 686d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 687d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 688d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return -1; 689d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 690d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 691d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 692d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Returns the GuidedActionsStylist that displays the button actions the user may take. 693d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return The GuidedActionsStylist for this fragment. 694d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 695d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public GuidedActionsStylist getGuidedButtonActionsStylist() { 696d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return mButtonActionsStylist; 697d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 698d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 699d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 700d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Sets the list of button GuidedActions that the user may take in this fragment. 701d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param actions The list of button GuidedActions for this fragment. 702d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 703d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public void setButtonActions(List<GuidedAction> actions) { 704d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActions = actions; 705d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu if (mButtonAdapter != null) { 706d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonAdapter.setActions(mButtonActions); 707d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 708d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 709d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 710d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 711d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Notify an button action has changed and update its UI. 712d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param position Position of the button GuidedAction in array. 713d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 714d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public void notifyButtonActionChanged(int position) { 715d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu if (mButtonAdapter != null) { 716d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonAdapter.notifyItemChanged(position); 717d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 718d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 719d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 720d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 721d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Returns the view corresponding to the button action at the indicated position in the list of 722d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * actions for this fragment. 723d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param position The integer position of the button action of interest. 724d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return The View corresponding to the button action at the indicated position, or null if 725d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * that action is not currently onscreen. 726d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 727d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public View getButtonActionItemView(int position) { 728d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu final RecyclerView.ViewHolder holder = mButtonActionsStylist.getActionsGridView() 729d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu .findViewHolderForPosition(position); 730d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return holder == null ? null : holder.itemView; 731d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 732d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 733d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 734d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Scrolls the action list to the position indicated, selecting that button action's view. 735d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @param position The integer position of the button action of interest. 736d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 737d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public void setSelectedButtonActionPosition(int position) { 738d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActionsStylist.getActionsGridView().setSelectedPosition(position); 739d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 740d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 741d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 742d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * Returns the position if the currently selected button GuidedAction. 743d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @return position The integer position of the currently selected button action. 744d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 745d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public int getSelectedButtonActionPosition() { 746d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return mButtonActionsStylist.getActionsGridView().getSelectedPosition(); 747d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 748d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 749d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 750ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the list of GuidedActions that the user may take in this fragment. 751ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The list of GuidedActions for this fragment. 752ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 753ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public List<GuidedAction> getActions() { 754ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return mActions; 755ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 756ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 757ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 758c1741246af607f6be2389056da0182c40f938348Dake Gu * Find GuidedAction by Id. 759c1741246af607f6be2389056da0182c40f938348Dake Gu * @param id Id of the action to search. 760c1741246af607f6be2389056da0182c40f938348Dake Gu * @return GuidedAction object or null if not found. 761c1741246af607f6be2389056da0182c40f938348Dake Gu */ 762c1741246af607f6be2389056da0182c40f938348Dake Gu public GuidedAction findActionById(long id) { 763c1741246af607f6be2389056da0182c40f938348Dake Gu int index = findActionPositionById(id); 764c1741246af607f6be2389056da0182c40f938348Dake Gu return index >= 0 ? mActions.get(index) : null; 765c1741246af607f6be2389056da0182c40f938348Dake Gu } 766c1741246af607f6be2389056da0182c40f938348Dake Gu 767c1741246af607f6be2389056da0182c40f938348Dake Gu /** 768c1741246af607f6be2389056da0182c40f938348Dake Gu * Find GuidedAction position in array by Id. 769c1741246af607f6be2389056da0182c40f938348Dake Gu * @param id Id of the action to search. 770c1741246af607f6be2389056da0182c40f938348Dake Gu * @return position of GuidedAction object in array or -1 if not found. 771c1741246af607f6be2389056da0182c40f938348Dake Gu */ 772c1741246af607f6be2389056da0182c40f938348Dake Gu public int findActionPositionById(long id) { 773c1741246af607f6be2389056da0182c40f938348Dake Gu if (mActions != null) { 774c1741246af607f6be2389056da0182c40f938348Dake Gu for (int i = 0; i < mActions.size(); i++) { 775c1741246af607f6be2389056da0182c40f938348Dake Gu GuidedAction action = mActions.get(i); 776c1741246af607f6be2389056da0182c40f938348Dake Gu if (mActions.get(i).getId() == id) { 777c1741246af607f6be2389056da0182c40f938348Dake Gu return i; 778c1741246af607f6be2389056da0182c40f938348Dake Gu } 779c1741246af607f6be2389056da0182c40f938348Dake Gu } 780c1741246af607f6be2389056da0182c40f938348Dake Gu } 781c1741246af607f6be2389056da0182c40f938348Dake Gu return -1; 782c1741246af607f6be2389056da0182c40f938348Dake Gu } 783c1741246af607f6be2389056da0182c40f938348Dake Gu 784c1741246af607f6be2389056da0182c40f938348Dake Gu /** 785ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Sets the list of GuidedActions that the user may take in this fragment. 786ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param actions The list of GuidedActions for this fragment. 787ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 788ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void setActions(List<GuidedAction> actions) { 789ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActions = actions; 790ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mAdapter != null) { 791ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mAdapter.setActions(mActions); 792ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 793ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 794ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 795ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 796c1741246af607f6be2389056da0182c40f938348Dake Gu * Notify an action has changed and update its UI. 797c1741246af607f6be2389056da0182c40f938348Dake Gu * @param position Position of the GuidedAction in array. 798c1741246af607f6be2389056da0182c40f938348Dake Gu */ 799c1741246af607f6be2389056da0182c40f938348Dake Gu public void notifyActionChanged(int position) { 800c1741246af607f6be2389056da0182c40f938348Dake Gu if (mAdapter != null) { 801c1741246af607f6be2389056da0182c40f938348Dake Gu mAdapter.notifyItemChanged(position); 802c1741246af607f6be2389056da0182c40f938348Dake Gu } 803c1741246af607f6be2389056da0182c40f938348Dake Gu } 804c1741246af607f6be2389056da0182c40f938348Dake Gu 805c1741246af607f6be2389056da0182c40f938348Dake Gu /** 806ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the view corresponding to the action at the indicated position in the list of 807ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * actions for this fragment. 808ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param position The integer position of the action of interest. 809ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The View corresponding to the action at the indicated position, or null if that 810ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * action is not currently onscreen. 811ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 812ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public View getActionItemView(int position) { 813d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu final RecyclerView.ViewHolder holder = mActionsStylist.getActionsGridView() 814d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu .findViewHolderForPosition(position); 815d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return holder == null ? null : holder.itemView; 816ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 817ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 818ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 819ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Scrolls the action list to the position indicated, selecting that action's view. 820ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param position The integer position of the action of interest. 821ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 822ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void setSelectedActionPosition(int position) { 823d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mActionsStylist.getActionsGridView().setSelectedPosition(position); 824ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 825ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 826ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 827ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the position if the currently selected GuidedAction. 828ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return position The integer position of the currently selected action. 829ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 830ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public int getSelectedActionPosition() { 831d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu return mActionsStylist.getActionsGridView().getSelectedPosition(); 832ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 833ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 834ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 8350b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * Called by Constructor to provide fragment transitions. The default implementation assigns 8360b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * transitions based on {@link #getUiStyle()}: 8370b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * <ul> 838517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li> {@link #UI_STYLE_REPLACE} Slide from/to end(right) for enter transition, slide from/to 8390b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * start(left) for exit transition, shared element enter transition is set to ChangeBounds. 8400b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * <li> {@link #UI_STYLE_ENTRANCE} Enter transition is set to slide from both sides, exit 841517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * transition is same as {@link #UI_STYLE_REPLACE}, no shared element enter transition. 8420b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * <li> {@link #UI_STYLE_ACTIVITY_ROOT} Enter transition is set to null and app should rely on 843517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * activity transition, exit transition is same as {@link #UI_STYLE_REPLACE}, no shared element 8440b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * enter transition. 8450b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * </ul> 8460b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * <p> 8470b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * The default implementation heavily relies on {@link GuidedActionsStylist} and 8480b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * {@link GuidanceStylist} layout, app may override this method when modifying the default 8490b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * layout of {@link GuidedActionsStylist} or {@link GuidanceStylist}. 85042ae32908312e63b474963fef789017c75feae37Dake Gu * <p> 8510b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * TIP: because the fragment view is removed during fragment transition, in general app cannot 8520b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * use two Visibility transition together. Workaround is to create your own Visibility 8530b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * transition that controls multiple animators (e.g. slide and fade animation in one Transition 8540b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu * class). 85542ae32908312e63b474963fef789017c75feae37Dake Gu */ 85642ae32908312e63b474963fef789017c75feae37Dake Gu protected void onProvideFragmentTransitions() { 85742ae32908312e63b474963fef789017c75feae37Dake Gu if (Build.VERSION.SDK_INT >= 21) { 858517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu final int uiStyle = getUiStyle(); 859517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu if (uiStyle == UI_STYLE_REPLACE) { 8608403619efebe94666c0615c3fc85080a303acf80Dake Gu Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END); 861517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true); 8628403619efebe94666c0615c3fc85080a303acf80Dake Gu TransitionHelper.setEnterTransition(this, enterTransition); 863517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu 864517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu Object changeBounds = TransitionHelper.createChangeBounds(false); 865517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu TransitionHelper.setSharedElementEnterTransition(this, changeBounds); 866517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu } else if (uiStyle == UI_STYLE_ENTRANCE) { 867e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata if (entranceTransitionType == SLIDE_FROM_SIDE) { 868e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN | 869e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.FADE_OUT); 870e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.include(fade, R.id.guidedstep_background); 871e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata Object slideFromSide = TransitionHelper.createFadeAndShortSlide(Gravity.END | Gravity.START); 872e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.include(slideFromSide, R.id.content_fragment); 873e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.include(slideFromSide, R.id.action_fragment_root); 874e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata Object enterTransition = TransitionHelper.createTransitionSet(false); 875e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.addTransition(enterTransition, fade); 876e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.addTransition(enterTransition, slideFromSide); 877e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.setEnterTransition(this, enterTransition); 878e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata } else { 879e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata Object slideFromBottom = TransitionHelper.createFadeAndShortSlide(Gravity.BOTTOM); 880e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.include(slideFromBottom, R.id.guidedstep_background_view_root); 881e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata Object enterTransition = TransitionHelper.createTransitionSet(false); 882e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.addTransition(enterTransition, slideFromBottom); 883e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata TransitionHelper.setEnterTransition(this, enterTransition); 884e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata } 8850b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu // No shared element transition 8860b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu TransitionHelper.setSharedElementEnterTransition(this, null); 887517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu } else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) { 88842ae32908312e63b474963fef789017c75feae37Dake Gu // for Activity root, we dont need enter transition, use activity transition 8898403619efebe94666c0615c3fc85080a303acf80Dake Gu TransitionHelper.setEnterTransition(this, null); 8900b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu // No shared element transition 8910b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu TransitionHelper.setSharedElementEnterTransition(this, null); 89242ae32908312e63b474963fef789017c75feae37Dake Gu } 8938e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu // exitTransition is same for all style 8948e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START); 8958e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true); 8968e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu TransitionHelper.setExitTransition(this, exitTransition); 89742ae32908312e63b474963fef789017c75feae37Dake Gu } 89842ae32908312e63b474963fef789017c75feae37Dake Gu } 89942ae32908312e63b474963fef789017c75feae37Dake Gu 90042ae32908312e63b474963fef789017c75feae37Dake Gu /** 901517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Called by onCreateView to inflate background view. Default implementation loads view 902517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * from {@link R.layout#lb_guidedstep_background} which holds a reference to 903517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * guidedStepBackground. 904517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @param inflater LayoutInflater to load background view. 905517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @param container Parent view of background view. 906517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @param savedInstanceState 907517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @return Created background view or null if no background. 90842ae32908312e63b474963fef789017c75feae37Dake Gu */ 909517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container, 910517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu Bundle savedInstanceState) { 911517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu return inflater.inflate(R.layout.lb_guidedstep_background, container, false); 91242ae32908312e63b474963fef789017c75feae37Dake Gu } 91342ae32908312e63b474963fef789017c75feae37Dake Gu 91442ae32908312e63b474963fef789017c75feae37Dake Gu /** 915517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Set UI style to fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when fragment 916517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * is first initialized. UI style is used to choose different fragment transition animations and 917517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * determine if this is the first GuidedStepFragment on backstack. In most cases app does not 918517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * directly call this method, app calls helper function 919517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * {@link #add(FragmentManager, GuidedStepFragment, int)}. However if the app creates Fragment 920517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * transaction and controls backstack by itself, it would need call setUiStyle() to select the 921517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * fragment transition to use. 92242ae32908312e63b474963fef789017c75feae37Dake Gu * 923517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or 924517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * {@link #UI_STYLE_ENTRANCE}. 92542ae32908312e63b474963fef789017c75feae37Dake Gu */ 92642ae32908312e63b474963fef789017c75feae37Dake Gu public void setUiStyle(int style) { 92742ae32908312e63b474963fef789017c75feae37Dake Gu int oldStyle = getUiStyle(); 92842ae32908312e63b474963fef789017c75feae37Dake Gu Bundle arguments = getArguments(); 929fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu boolean isNew = false; 93042ae32908312e63b474963fef789017c75feae37Dake Gu if (arguments == null) { 93142ae32908312e63b474963fef789017c75feae37Dake Gu arguments = new Bundle(); 932fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu isNew = true; 93342ae32908312e63b474963fef789017c75feae37Dake Gu } 93442ae32908312e63b474963fef789017c75feae37Dake Gu arguments.putInt(EXTRA_UI_STYLE, style); 93542ae32908312e63b474963fef789017c75feae37Dake Gu // call setArgument() will validate if the fragment is already added. 936fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu if (isNew) { 937fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu setArguments(arguments); 938fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu } 93942ae32908312e63b474963fef789017c75feae37Dake Gu if (style != oldStyle) { 94042ae32908312e63b474963fef789017c75feae37Dake Gu onProvideFragmentTransitions(); 94142ae32908312e63b474963fef789017c75feae37Dake Gu } 94242ae32908312e63b474963fef789017c75feae37Dake Gu } 94342ae32908312e63b474963fef789017c75feae37Dake Gu 94442ae32908312e63b474963fef789017c75feae37Dake Gu /** 945517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Read UI style from fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when 946517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * fragment is first initialized. UI style is used to choose different fragment transition 947517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * animations and determine if this is the first GuidedStepFragment on backstack. 94842ae32908312e63b474963fef789017c75feae37Dake Gu * 949517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or 95042ae32908312e63b474963fef789017c75feae37Dake Gu * {@link #UI_STYLE_ENTRANCE}. 951517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * @see #onProvideFragmentTransitions() 95242ae32908312e63b474963fef789017c75feae37Dake Gu */ 95342ae32908312e63b474963fef789017c75feae37Dake Gu public int getUiStyle() { 95442ae32908312e63b474963fef789017c75feae37Dake Gu Bundle b = getArguments(); 955517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu if (b == null) return UI_STYLE_ENTRANCE; 956517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu return b.getInt(EXTRA_UI_STYLE, UI_STYLE_ENTRANCE); 95742ae32908312e63b474963fef789017c75feae37Dake Gu } 95842ae32908312e63b474963fef789017c75feae37Dake Gu 95942ae32908312e63b474963fef789017c75feae37Dake Gu /** 960ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 961ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 962ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 963ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onCreate(Bundle savedInstanceState) { 964ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing super.onCreate(savedInstanceState); 965ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (DEBUG) Log.v(TAG, "onCreate"); 96642ae32908312e63b474963fef789017c75feae37Dake Gu // Set correct transition from saved arguments. 96742ae32908312e63b474963fef789017c75feae37Dake Gu onProvideFragmentTransitions(); 968ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Bundle state = (savedInstanceState != null) ? savedInstanceState : getArguments(); 969ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (state != null) { 970ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mSelectedIndex == -1) { 971ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mSelectedIndex = state.getInt(EXTRA_ACTION_SELECTED_INDEX, -1); 972ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 973ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 974d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu ArrayList<GuidedAction> actions = new ArrayList<GuidedAction>(); 975d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu onCreateActions(actions, savedInstanceState); 9769050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu if (savedInstanceState != null) { 9779050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu onRestoreActions(actions, savedInstanceState); 9789050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 979d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu setActions(actions); 980d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu ArrayList<GuidedAction> buttonActions = new ArrayList<GuidedAction>(); 981d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu onCreateButtonActions(buttonActions, savedInstanceState); 9829050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu if (savedInstanceState != null) { 9839050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu onRestoreButtonActions(buttonActions, savedInstanceState); 9849050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 985d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu setButtonActions(buttonActions); 986d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 987d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 988d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu /** 989d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * {@inheritDoc} 990d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu */ 991d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu @Override 992d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu public void onDestroyView() { 993d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mGuidanceStylist.onDestroyView(); 994d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mActionsStylist.onDestroyView(); 995d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActionsStylist.onDestroyView(); 99643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mAdapter = null; 997be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mSubAdapter = null; 99843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mButtonAdapter = null; 99943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mAdapterGroup = null; 1000d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu super.onDestroyView(); 1001ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1002ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1003ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 1004ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 1005ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 1006ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 1007ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public View onCreateView(LayoutInflater inflater, ViewGroup container, 1008ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Bundle savedInstanceState) { 1009ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (DEBUG) Log.v(TAG, "onCreateView"); 1010ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1011ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing resolveTheme(); 1012ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing inflater = getThemeInflater(inflater); 1013ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1014b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu GuidedStepRootLayout root = (GuidedStepRootLayout) inflater.inflate( 1015b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu R.layout.lb_guidedstep_fragment, container, false); 101668d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata 1017b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu root.setFocusOutStart(isFocusOutStartAllowed()); 1018b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu root.setFocusOutEnd(isFocusOutEndAllowed()); 101968d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata 1020517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu ViewGroup guidanceContainer = (ViewGroup) root.findViewById(R.id.content_fragment); 1021517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu ViewGroup actionContainer = (ViewGroup) root.findViewById(R.id.action_fragment); 1022ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1023ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Guidance guidance = onCreateGuidance(savedInstanceState); 1024ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing View guidanceView = mGuidanceStylist.onCreateView(inflater, guidanceContainer, guidance); 1025ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing guidanceContainer.addView(guidanceView); 1026ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1027ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing View actionsView = mActionsStylist.onCreateView(inflater, actionContainer); 1028ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing actionContainer.addView(actionsView); 1029ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1030d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu View buttonActionsView = mButtonActionsStylist.onCreateView(inflater, actionContainer); 1031d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu actionContainer.addView(buttonActionsView); 1032d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 10334158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing GuidedActionAdapter.EditListener editListener = new GuidedActionAdapter.EditListener() { 1034c1741246af607f6be2389056da0182c40f938348Dake Gu 10354158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing @Override 1036c1741246af607f6be2389056da0182c40f938348Dake Gu public void onImeOpen() { 1037c1741246af607f6be2389056da0182c40f938348Dake Gu runImeAnimations(true); 1038c1741246af607f6be2389056da0182c40f938348Dake Gu } 1039c1741246af607f6be2389056da0182c40f938348Dake Gu 1040c1741246af607f6be2389056da0182c40f938348Dake Gu @Override 1041c1741246af607f6be2389056da0182c40f938348Dake Gu public void onImeClose() { 1042c1741246af607f6be2389056da0182c40f938348Dake Gu runImeAnimations(false); 1043c1741246af607f6be2389056da0182c40f938348Dake Gu } 1044c1741246af607f6be2389056da0182c40f938348Dake Gu 1045c1741246af607f6be2389056da0182c40f938348Dake Gu @Override 1046bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu public long onGuidedActionEditedAndProceed(GuidedAction action) { 1047c1741246af607f6be2389056da0182c40f938348Dake Gu return GuidedStepFragment.this.onGuidedActionEditedAndProceed(action); 10484158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 1049bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu 1050bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu @Override 105116ab389e0bd11594059f8164a1477045ee625154Dake Gu public void onGuidedActionEditCanceled(GuidedAction action) { 105216ab389e0bd11594059f8164a1477045ee625154Dake Gu GuidedStepFragment.this.onGuidedActionEditCanceled(action); 1053bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu } 10544158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing }; 10554158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 1056be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mAdapter = new GuidedActionAdapter(mActions, new GuidedActionAdapter.ClickListener() { 1057be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu @Override 1058be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void onGuidedActionClicked(GuidedAction action) { 1059be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedStepFragment.this.onGuidedActionClicked(action); 1060be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu if (isSubActionsExpanded()) { 1061be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu collapseSubActions(); 1062be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } else if (action.hasSubActions()) { 1063be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu expandSubActions(action); 1064be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 1065be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 1066be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu }, this, mActionsStylist, false); 1067be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mButtonAdapter = 1068be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu new GuidedActionAdapter(mButtonActions, new GuidedActionAdapter.ClickListener() { 1069be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu @Override 1070be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void onGuidedActionClicked(GuidedAction action) { 1071be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedStepFragment.this.onGuidedActionClicked(action); 1072be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 1073be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu }, this, mButtonActionsStylist, false); 1074be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mSubAdapter = new GuidedActionAdapter(null, new GuidedActionAdapter.ClickListener() { 1075be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu @Override 1076be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void onGuidedActionClicked(GuidedAction action) { 10771ed9dc77616514e20c51baa67a04adab42e4135eDake Gu if (mActionsStylist.isInExpandTransition()) { 10781ed9dc77616514e20c51baa67a04adab42e4135eDake Gu return; 10791ed9dc77616514e20c51baa67a04adab42e4135eDake Gu } 1080be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu if (GuidedStepFragment.this.onSubGuidedActionClicked(action)) { 1081be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu collapseSubActions(); 1082be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 1083be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 1084be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu }, this, mActionsStylist, true); 108543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mAdapterGroup = new GuidedActionAdapterGroup(); 1086be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mAdapterGroup.addAdpter(mAdapter, mButtonAdapter); 1087be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mAdapterGroup.addAdpter(mSubAdapter, null); 108843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mAdapterGroup.setEditListener(editListener); 1089b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu mActionsStylist.setEditListener(editListener); 1090d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 1091d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mActionsStylist.getActionsGridView().setAdapter(mAdapter); 1092be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu if (mActionsStylist.getSubActionsGridView() != null) { 1093be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mActionsStylist.getSubActionsGridView().setAdapter(mSubAdapter); 1094be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu } 1095d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActionsStylist.getActionsGridView().setAdapter(mButtonAdapter); 1096d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu if (mButtonActions.size() == 0) { 10970b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu // when there is no button actions, we dont need show the second panel, but keep 10980b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu // the width zero to run ChangeBounds transition. 10990b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 11000b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu buttonActionsView.getLayoutParams(); 11010b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu lp.weight = 0; 11020b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu buttonActionsView.setLayoutParams(lp); 1103d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } else { 11040b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu // when there are two actions panel, we need adjust the weight of action to 11050b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu // guidedActionContentWidthWeightTwoPanels. 1106d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu Context ctx = mThemeWrapper != null ? mThemeWrapper : getActivity(); 1107d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu TypedValue typedValue = new TypedValue(); 1108d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu if (ctx.getTheme().resolveAttribute(R.attr.guidedActionContentWidthWeightTwoPanels, 1109d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu typedValue, true)) { 1110517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu View actionsRoot = root.findViewById(R.id.action_fragment_root); 1111d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu float weight = typedValue.getFloat(); 1112d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) actionsRoot 1113d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu .getLayoutParams(); 1114d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu lp.weight = weight; 1115d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu actionsRoot.setLayoutParams(lp); 1116d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 1117d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu } 1118ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1119ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing int pos = (mSelectedIndex >= 0 && mSelectedIndex < mActions.size()) ? 1120ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mSelectedIndex : getFirstCheckedAction(); 1121d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu setSelectedActionPosition(pos); 1122d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu 1123d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu setSelectedButtonActionPosition(0); 1124ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 112568d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata // Add the background view. 1126517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu View backgroundView = onCreateBackgroundView(inflater, root, savedInstanceState); 1127517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu if (backgroundView != null) { 112868d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata FrameLayout backgroundViewRoot = (FrameLayout)root.findViewById( 112968d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata R.id.guidedstep_background_view_root); 113068d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata backgroundViewRoot.addView(backgroundView, 0); 1131517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu } 1132517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu return root; 1133ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1134ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 11355b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu @Override 11365b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu public void onResume() { 11375b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu super.onResume(); 11385b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu getView().findViewById(R.id.action_fragment).requestFocus(); 11395b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu } 11405b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu 1141ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 11429050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu * Get the key will be used to save GuidedAction with Fragment. 11439050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu * @param action GuidedAction to get key. 11449050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu * @return Key to save the GuidedAction. 11459050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu */ 11469050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final String getAutoRestoreKey(GuidedAction action) { 11479050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu return EXTRA_ACTION_PREFIX + action.getId(); 11489050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11499050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11509050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu /** 11519050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu * Get the key will be used to save GuidedAction with Fragment. 11529050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu * @param action GuidedAction to get key. 11539050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu * @return Key to save the GuidedAction. 11549050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu */ 11559050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final String getButtonAutoRestoreKey(GuidedAction action) { 11569050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu return EXTRA_BUTTON_ACTION_PREFIX + action.getId(); 11579050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11589050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11599050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final static boolean isSaveEnabled(GuidedAction action) { 11609050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu return action.isAutoSaveRestoreEnabled() && action.getId() != GuidedAction.NO_ID; 11619050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11629050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11639050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final void onRestoreActions(List<GuidedAction> actions, Bundle savedInstanceState) { 11649050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu for (int i = 0, size = actions.size(); i < size; i++) { 11659050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu GuidedAction action = actions.get(i); 11669050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu if (isSaveEnabled(action)) { 11679050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu action.onRestoreInstanceState(savedInstanceState, getAutoRestoreKey(action)); 11689050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11699050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11709050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11719050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11729050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final void onRestoreButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) { 11739050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu for (int i = 0, size = actions.size(); i < size; i++) { 11749050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu GuidedAction action = actions.get(i); 11759050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu if (isSaveEnabled(action)) { 11769050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu action.onRestoreInstanceState(savedInstanceState, getButtonAutoRestoreKey(action)); 11779050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11789050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11799050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11809050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11819050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final void onSaveActions(List<GuidedAction> actions, Bundle outState) { 11829050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu for (int i = 0, size = actions.size(); i < size; i++) { 11839050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu GuidedAction action = actions.get(i); 11849050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu if (isSaveEnabled(action)) { 11859050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu action.onSaveInstanceState(outState, getAutoRestoreKey(action)); 11869050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11879050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11889050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11899050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11909050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu final void onSaveButtonActions(List<GuidedAction> actions, Bundle outState) { 11919050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu for (int i = 0, size = actions.size(); i < size; i++) { 11929050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu GuidedAction action = actions.get(i); 11939050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu if (isSaveEnabled(action)) { 11949050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu action.onSaveInstanceState(outState, getButtonAutoRestoreKey(action)); 11959050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11969050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11979050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu } 11989050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu 11999050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu /** 1200ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 1201ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 1202ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 1203ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onSaveInstanceState(Bundle outState) { 1204ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing super.onSaveInstanceState(outState); 12059050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu onSaveActions(mActions, outState); 12069050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu onSaveButtonActions(mButtonActions, outState); 1207ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing outState.putInt(EXTRA_ACTION_SELECTED_INDEX, 1208d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu (mActionsStylist.getActionsGridView() != null) ? 1209d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu getSelectedActionPosition() : mSelectedIndex); 1210ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1211ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 121242ae32908312e63b474963fef789017c75feae37Dake Gu private static boolean isGuidedStepTheme(Context context) { 1213ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing int resId = R.attr.guidedStepThemeFlag; 1214ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing TypedValue typedValue = new TypedValue(); 1215ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing boolean found = context.getTheme().resolveAttribute(resId, typedValue, true); 1216ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (DEBUG) Log.v(TAG, "Found guided step theme flag? " + found); 1217ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return found && typedValue.type == TypedValue.TYPE_INT_BOOLEAN && typedValue.data != 0; 1218ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1219ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 122037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu /** 122137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * Convenient method to close GuidedStepFragments on top of other content or finish Activity if 122237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * GuidedStepFragments were started in a separate activity. Pops all stack entries including 122337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * {@link #UI_STYLE_ENTRANCE}; if {@link #UI_STYLE_ENTRANCE} is not found, finish the activity. 1224517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * Note that this method must be paired with {@link #add(FragmentManager, GuidedStepFragment, 1225517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * int)} which sets up the stack entry name for finding which fragment we need to pop back to. 122637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu */ 122737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu public void finishGuidedStepFragments() { 122837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu final FragmentManager fragmentManager = getFragmentManager(); 122937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu final int entryCount = fragmentManager.getBackStackEntryCount(); 123037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu if (entryCount > 0) { 123137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu for (int i = entryCount - 1; i >= 0; i--) { 123237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu BackStackEntry entry = fragmentManager.getBackStackEntryAt(i); 1233fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu if (isStackEntryUiStyleEntrance(entry.getName())) { 1234fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu GuidedStepFragment top = getCurrentGuidedStepFragment(fragmentManager); 1235fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu if (top != null) { 1236fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu top.setUiStyle(UI_STYLE_ENTRANCE); 1237fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu } 123837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu fragmentManager.popBackStack(entry.getId(), 123937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu FragmentManager.POP_BACK_STACK_INCLUSIVE); 124037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return; 124137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 124237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 124337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 124437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu ActivityCompat.finishAfterTransition(getActivity()); 124537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 124637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 124737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu /** 124837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * Convenient method to pop to fragment with Given class. 124937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @param guidedStepFragmentClass Name of the Class of GuidedStepFragment to pop to. 125037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu * @param flags Either 0 or {@link FragmentManager#POP_BACK_STACK_INCLUSIVE}. 125137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu */ 125237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu public void popBackStackToGuidedStepFragment(Class guidedStepFragmentClass, int flags) { 125337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu if (!GuidedStepFragment.class.isAssignableFrom(guidedStepFragmentClass)) { 125437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return; 125537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 125637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu final FragmentManager fragmentManager = getFragmentManager(); 125737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu final int entryCount = fragmentManager.getBackStackEntryCount(); 125837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu String className = guidedStepFragmentClass.getName(); 125937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu if (entryCount > 0) { 126037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu for (int i = entryCount - 1; i >= 0; i--) { 126137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu BackStackEntry entry = fragmentManager.getBackStackEntryAt(i); 126237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu String entryClassName = getGuidedStepFragmentClassName(entry.getName()); 126337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu if (className.equals(entryClassName)) { 126437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu fragmentManager.popBackStack(entry.getId(), flags); 126537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu return; 126637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 126737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 126837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 126937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu } 127037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu 1271b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu /** 1272b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * Returns true if allows focus out of start edge of GuidedStepFragment, false otherwise. 1273b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * Default value is false, the reason is to disable FocusFinder to find focusable views 1274b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * beneath content of GuidedStepFragment. Subclass may override. 1275b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * @return True if allows focus out of start edge of GuidedStepFragment. 1276b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu */ 1277b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu public boolean isFocusOutStartAllowed() { 1278b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu return false; 1279b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu } 1280b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu 1281b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu /** 1282b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * Returns true if allows focus out of end edge of GuidedStepFragment, false otherwise. 1283b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * Default value is false, the reason is to disable FocusFinder to find focusable views 1284b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * beneath content of GuidedStepFragment. Subclass may override. 1285b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu * @return True if allows focus out of end edge of GuidedStepFragment. 1286b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu */ 1287b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu public boolean isFocusOutEndAllowed() { 1288b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu return false; 1289b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu } 1290b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu 1291e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata /** 1292e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * Sets the transition type to be used for {@link #UI_STYLE_ENTRANCE} animation. 1293e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * Currently we provide 2 different variations for animation - slide in from 1294e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * side (default) or bottom. 1295e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * 1296e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * Ideally we can retireve the screen mode settings from the theme attribute 1297e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * {@code Theme.Leanback.GuidedStep#guidedStepHeightWeight} and use that to 1298e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * determine the transition. But the fragment context to retrieve the theme 1299e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * isn't available on platform v23 or earlier. 1300e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * 1301e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * For now clients(subclasses) can call this method inside the contructor. 1302e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata * @hide 1303e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata */ 1304e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata public void setEntranceTransitionType(int transitionType) { 1305e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata this.entranceTransitionType = transitionType; 1306e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata } 1307e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata 1308ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private void resolveTheme() { 1309ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // Look up the guidedStepTheme in the currently specified theme. If it exists, 1310ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // replace the theme with its value. 1311ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Activity activity = getActivity(); 1312ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mTheme == -1 && !isGuidedStepTheme(activity)) { 1313ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // Look up the guidedStepTheme in the activity's currently specified theme. If it 1314ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // exists, replace the theme with its value. 1315ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing int resId = R.attr.guidedStepTheme; 1316ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing TypedValue typedValue = new TypedValue(); 1317ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing boolean found = activity.getTheme().resolveAttribute(resId, typedValue, true); 1318ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (DEBUG) Log.v(TAG, "Found guided step theme reference? " + found); 1319ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (found) { 132042ae32908312e63b474963fef789017c75feae37Dake Gu ContextThemeWrapper themeWrapper = 132142ae32908312e63b474963fef789017c75feae37Dake Gu new ContextThemeWrapper(activity, typedValue.resourceId); 132242ae32908312e63b474963fef789017c75feae37Dake Gu if (isGuidedStepTheme(themeWrapper)) { 1323ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mTheme = typedValue.resourceId; 132442ae32908312e63b474963fef789017c75feae37Dake Gu mThemeWrapper = themeWrapper; 1325ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } else { 1326ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing found = false; 132742ae32908312e63b474963fef789017c75feae37Dake Gu mThemeWrapper = null; 1328ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1329ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1330ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (!found) { 1331ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Log.e(TAG, "GuidedStepFragment does not have an appropriate theme set."); 1332ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 133342ae32908312e63b474963fef789017c75feae37Dake Gu } else if (mTheme != -1) { 133442ae32908312e63b474963fef789017c75feae37Dake Gu mThemeWrapper = new ContextThemeWrapper(activity, mTheme); 1335ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1336ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1337ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1338ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private LayoutInflater getThemeInflater(LayoutInflater inflater) { 1339ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mTheme == -1) { 1340ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return inflater; 1341ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } else { 134242ae32908312e63b474963fef789017c75feae37Dake Gu return inflater.cloneInContext(mThemeWrapper); 1343ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1344ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1345ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 1346ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private int getFirstCheckedAction() { 1347ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing for (int i = 0, size = mActions.size(); i < size; i++) { 1348ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mActions.get(i).isChecked()) { 1349ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return i; 1350ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1351ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1352ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return 0; 1353ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 1354ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 13554158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing private void runImeAnimations(boolean entering) { 13564158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing ArrayList<Animator> animators = new ArrayList<Animator>(); 13574158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing if (entering) { 13584158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing mGuidanceStylist.onImeAppearing(animators); 13594158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing mActionsStylist.onImeAppearing(animators); 1360d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActionsStylist.onImeAppearing(animators); 13614158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } else { 13624158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing mGuidanceStylist.onImeDisappearing(animators); 13634158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing mActionsStylist.onImeDisappearing(animators); 1364d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu mButtonActionsStylist.onImeDisappearing(animators); 13654158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 13664158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing AnimatorSet set = new AnimatorSet(); 13674158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing set.playTogether(animators); 13684158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing set.start(); 13694158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 13704158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 1371ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing} 1372