[go: nahoru, domu]

14e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu/* This file is auto-generated from GuidedStepFragment.java.  DO NOT MODIFY. */
24e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
34e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu/*
44e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Copyright (C) 2015 The Android Open Source Project
54e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu *
64e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
74e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * in compliance with the License. You may obtain a copy of the License at
84e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu *
94e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * http://www.apache.org/licenses/LICENSE-2.0
104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu *
114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * or implied. See the License for the specific language governing permissions and limitations under
144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * the License.
154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu */
164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gupackage android.support.v17.leanback.app;
174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.animation.Animator;
194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.animation.AnimatorSet;
204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v4.app.FragmentActivity;
214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v4.app.Fragment;
224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v4.app.FragmentManager;
2337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Guimport android.support.v4.app.FragmentManager.BackStackEntry;
244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v4.app.FragmentTransaction;
254e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.content.Context;
264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.os.Build;
274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.os.Bundle;
284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.annotation.NonNull;
294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v17.leanback.R;
3068d693985e85ee5eed18f78beaaadbfd9b8a4f13susnataimport android.support.v17.leanback.transition.TransitionHelper;
314e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v17.leanback.widget.GuidanceStylist;
324e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v17.leanback.widget.GuidanceStylist.Guidance;
334e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v17.leanback.widget.GuidedAction;
34be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport android.support.v17.leanback.widget.GuidedActionAdapter;
35be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport android.support.v17.leanback.widget.GuidedActionAdapterGroup;
364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.support.v17.leanback.widget.GuidedActionsStylist;
37be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport android.support.v17.leanback.widget.ViewHolderTask;
3837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Guimport android.support.v4.app.ActivityCompat;
39d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Guimport android.support.v7.widget.RecyclerView;
404e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.util.Log;
414e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.util.TypedValue;
424e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.view.ContextThemeWrapper;
434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.view.Gravity;
444e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.view.LayoutInflater;
454e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.view.View;
464e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport android.view.ViewGroup;
4768d693985e85ee5eed18f78beaaadbfd9b8a4f13susnataimport android.widget.FrameLayout;
48d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Guimport android.widget.LinearLayout;
494e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport java.util.ArrayList;
514e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Guimport java.util.List;
524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu/**
544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * A GuidedStepSupportFragment is used to guide the user through a decision or series of decisions.
554e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * It is composed of a guidance view on the left and a view on the right containing a list of
564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * possible actions.
574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
584e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <h3>Basic Usage</h3>
594e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
604e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Clients of GuidedStepSupportFragment must create a custom subclass to attach to their Activities.
614e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * This custom subclass provides the information necessary to construct the user interface and
624e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * respond to user actions. At a minimum, subclasses should override:
634e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <ul>
644e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>{@link #onCreateGuidance}, to provide instructions to the user</li>
654e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>{@link #onCreateActions}, to provide a set of {@link GuidedAction}s the user can take</li>
664e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>{@link #onGuidedActionClicked}, to respond to those actions</li>
674e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * </ul>
684e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
694e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Clients use following helper functions to add GuidedStepSupportFragment to Activity or FragmentManager:
704e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <ul>
7147d21fb23abd7099f1bcfc08365ec9f946f0f6d8Dake Gu * <li>{@link #addAsRoot(FragmentActivity, GuidedStepSupportFragment, int)}, to be called during Activity onCreate,
724e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * adds GuidedStepSupportFragment as the first Fragment in activity.</li>
734e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>{@link #add(FragmentManager, GuidedStepSupportFragment)} or {@link #add(FragmentManager,
744e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * GuidedStepSupportFragment, int)}, to add GuidedStepSupportFragment on top of existing Fragments or
754e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * replacing existing GuidedStepSupportFragment when moving forward to next step.</li>
76517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>{@link #finishGuidedStepSupportFragments()} can either finish the activity or pop all
77517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * GuidedStepSupportFragment from stack.
78517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * <li>If app chooses not to use the helper function, it is the app's responsibility to call
79517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * {@link #setUiStyle(int)} to select fragment transition and remember the stack entry where it
80517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu * need pops to.
814e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * </ul>
824e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <h3>Theming and Stylists</h3>
834e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
844e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * GuidedStepSupportFragment delegates its visual styling to classes called stylists. The {@link
854e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * GuidanceStylist} is responsible for the left guidance view, while the {@link
864e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * GuidedActionsStylist} is responsible for the right actions view. The stylists use theme
874e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * attributes to derive values associated with the presentation, such as colors, animations, etc.
884e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Most simple visual aspects of GuidanceStylist and GuidedActionsStylist can be customized
894e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * via theming; see their documentation for more information.
904e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
914e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * GuidedStepSupportFragments must have access to an appropriate theme in order for the stylists to
924e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * function properly.  Specifically, the fragment must receive {@link
934e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * android.support.v17.leanback.R.style#Theme_Leanback_GuidedStep}, or a theme whose parent is
944e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * is set to that theme. Themes can be provided in one of three ways:
954e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <ul>
964e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>The simplest way is to set the theme for the host Activity to the GuidedStep theme or a
974e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * theme that derives from it.</li>
984e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>If the Activity already has a theme and setting its parent theme is inconvenient, the
994e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * existing Activity theme can have an entry added for the attribute {@link
1004e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme}. If present,
1014e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * this theme will be used by GuidedStepSupportFragment as an overlay to the Activity's theme.</li>
1024e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <li>Finally, custom subclasses of GuidedStepSupportFragment may provide a theme through the {@link
1034e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * #onProvideTheme} method. This can be useful if a subclass is used across multiple
1044e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * Activities.</li>
1054e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * </ul>
1064e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
1074e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * If the theme is provided in multiple ways, the onProvideTheme override has priority, followed by
1084e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * the Activty's theme.  (Themes whose parent theme is already set to the guided step theme do not
1094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * need to set the guidedStepTheme attribute; if set, it will be ignored.)
1104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
1114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * If themes do not provide enough customizability, the stylists themselves may be subclassed and
1124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * provided to the GuidedStepSupportFragment through the {@link #onCreateGuidanceStylist} and {@link
1134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * #onCreateActionsStylist} methods.  The stylists have simple hooks so that subclasses
1144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * may override layout files; subclasses may also have more complex logic to determine styling.
1154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
1164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <h3>Guided sequences</h3>
1174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
1184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * GuidedStepSupportFragments can be grouped together to provide a guided sequence. GuidedStepSupportFragments
1194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * grouped as a sequence use custom animations provided by {@link GuidanceStylist} and
1204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * {@link GuidedActionsStylist} (or subclasses) during transitions between steps. Clients
1214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * should use {@link #add} to place subsequent GuidedFragments onto the fragment stack so that
1224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * custom animations are properly configured. (Custom animations are triggered automatically when
1234e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * the fragment stack is subsequently popped by any normal mechanism.)
1244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <p>
1254e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * <i>Note: Currently GuidedStepSupportFragments grouped in this way must all be defined programmatically,
1264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * rather than in XML. This restriction may be removed in the future.</i>
1274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu *
1284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepTheme
1294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepBackground
130d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeight
131d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionContentWidthWeightTwoPanels
132d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackground
1337f43e18536eae40705d5c63830e9edb283f196adDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsBackgroundDark
134a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsElevation
1354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * @see GuidanceStylist
1364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * @see GuidanceStylist.Guidance
1374e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * @see GuidedAction
1384e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu * @see GuidedActionsStylist
1394e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu */
140be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gupublic class GuidedStepSupportFragment extends Fragment implements GuidedActionAdapter.FocusListener {
1414e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
1424e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private static final String TAG_LEAN_BACK_ACTIONS_FRAGMENT = "leanBackGuidedStepSupportFragment";
1434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private static final String EXTRA_ACTION_SELECTED_INDEX = "selectedIndex";
1449050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    private static final String EXTRA_ACTION_PREFIX = "action_";
1459050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    private static final String EXTRA_BUTTON_ACTION_PREFIX = "buttonaction_";
1464e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
147517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu    private static final String ENTRY_NAME_REPLACE = "GuidedStepDefault";
14837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
14937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    private static final String ENTRY_NAME_ENTRANCE = "GuidedStepEntrance";
15037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
151e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu    private static final boolean IS_FRAMEWORK_FRAGMENT = false;
152e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu
1534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
154fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * Fragment argument name for UI style.  The argument value is persisted in fragment state and
155fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * used to select fragment transition. The value is initially {@link #UI_STYLE_ENTRANCE} and
156fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * might be changed in one of the three helper functions:
1574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <ul>
158fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * <li>{@link #addAsRoot(FragmentActivity, GuidedStepSupportFragment, int)} sets to
159fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * {@link #UI_STYLE_ACTIVITY_ROOT}</li>
1604e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <li>{@link #add(FragmentManager, GuidedStepSupportFragment)} or {@link #add(FragmentManager,
161fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * GuidedStepSupportFragment, int)} sets it to {@link #UI_STYLE_REPLACE} if there is already a
162fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * GuidedStepSupportFragment on stack.</li>
163fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * <li>{@link #finishGuidedStepSupportFragments()} changes current GuidedStepSupportFragment to
164fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * {@link #UI_STYLE_ENTRANCE} for the non activity case.  This is a special case that changes
165fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * the transition settings after fragment has been created,  in order to force current
166fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * GuidedStepSupportFragment run a return transition of {@link #UI_STYLE_ENTRANCE}</li>
1674e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * </ul>
1684e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <p>
1694e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Argument value can be either:
1704e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <ul>
171517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li>{@link #UI_STYLE_REPLACE}</li>
1724e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <li>{@link #UI_STYLE_ENTRANCE}</li>
1734e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <li>{@link #UI_STYLE_ACTIVITY_ROOT}</li>
1744e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * </ul>
1754e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
1764e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static final String EXTRA_UI_STYLE = "uiStyle";
1774e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
1784e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
179517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * This is the case that we use GuidedStepSupportFragment to replace another existing
180517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * GuidedStepSupportFragment when moving forward to next step. Default behavior of this style is:
1814e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <ul>
182517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li>Enter transition slides in from END(right), exit transition same as
183517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * {@link #UI_STYLE_ENTRANCE}.
1844e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * </li>
1854e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * </ul>
1864e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
187517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu    public static final int UI_STYLE_REPLACE = 0;
1884e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
1894e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
190c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu     * @deprecated Same value as {@link #UI_STYLE_REPLACE}.
191c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu     */
192c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu    @Deprecated
193c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu    public static final int UI_STYLE_DEFAULT = 0;
194c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu
195c3d11aea44660bf77326f6f07ebf11c6a19f7e1fDake Gu    /**
196517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Default value for argument {@link #EXTRA_UI_STYLE}. The default value is assigned in
197517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * GuidedStepSupportFragment constructor. This is the case that we show GuidedStepSupportFragment on top of
198517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * other content. The default behavior of this style:
1994e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <ul>
200517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li>Enter transition slides in from two sides, exit transition slide out to START(left).
201517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Background will be faded in. Note: Changing exit transition by UI style is not working
202517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * because fragment transition asks for exit transition before UI style is restored in Fragment
2034e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * .onCreate().</li>
2044e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * </ul>
205fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * When popping multiple GuidedStepSupportFragment, {@link #finishGuidedStepSupportFragments()} also changes
206fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * the top GuidedStepSupportFragment to UI_STYLE_ENTRANCE in order to run the return transition
207fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * (reverse of enter transition) of UI_STYLE_ENTRANCE.
2084e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
2094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static final int UI_STYLE_ENTRANCE = 1;
2104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
2114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
212517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * One possible value of argument {@link #EXTRA_UI_STYLE}. This is the case that we show first
213517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * GuidedStepSupportFragment in a separate activity. The default behavior of this style:
2144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <ul>
215517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li>Enter transition is assigned null (will rely on activity transition), exit transition is
216517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * same as {@link #UI_STYLE_ENTRANCE}. Note: Changing exit transition by UI style is not working
217ce4c2014042fe6e4723bab30741039848adcf4beDake Gu     * because fragment transition asks for exit transition before UI style is restored in
2184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Fragment.onCreate().</li>
2194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * </ul>
2204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
2214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static final int UI_STYLE_ACTIVITY_ROOT = 2;
2224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
223e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    /**
224e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * Animation to slide the contents from the side (left/right).
225e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * @hide
226e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     */
227e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    public static final int SLIDE_FROM_SIDE = 0;
228e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata
229e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    /**
230e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * Animation to slide the contents from the bottom.
231e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * @hide
232e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     */
233e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    public static final int SLIDE_FROM_BOTTOM = 1;
234e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata
2354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private static final String TAG = "GuidedStepSupportFragment";
2364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private static final boolean DEBUG = false;
2374e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
238e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu    /**
239e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu     * @hide
240e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu     */
241e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu    public static class DummyFragment extends Fragment {
242e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu        @Override
243e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu        public View onCreateView(LayoutInflater inflater, ViewGroup container,
244e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu                Bundle savedInstanceState) {
245e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu            final View v = new View(inflater.getContext());
246e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu            v.setVisibility(View.GONE);
247e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu            return v;
248e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu        }
249e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu    }
250e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu
2514e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private int mTheme;
2524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private ContextThemeWrapper mThemeWrapper;
2534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private GuidanceStylist mGuidanceStylist;
2544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private GuidedActionsStylist mActionsStylist;
255d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    private GuidedActionsStylist mButtonActionsStylist;
2564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private GuidedActionAdapter mAdapter;
257be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    private GuidedActionAdapter mSubAdapter;
258d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    private GuidedActionAdapter mButtonAdapter;
25943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu    private GuidedActionAdapterGroup mAdapterGroup;
2604e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private List<GuidedAction> mActions = new ArrayList<GuidedAction>();
261d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    private List<GuidedAction> mButtonActions = new ArrayList<GuidedAction>();
2624e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private int mSelectedIndex = -1;
263d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    private int mButtonSelectedIndex = -1;
264e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    private int entranceTransitionType = SLIDE_FROM_SIDE;
2654e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
2664e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public GuidedStepSupportFragment() {
2674e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // We need to supply the theme before any potential call to onInflate in order
2684e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // for the defaulting to work properly.
2694e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        mTheme = onProvideTheme();
2704e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        mGuidanceStylist = onCreateGuidanceStylist();
2714e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        mActionsStylist = onCreateActionsStylist();
272d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mButtonActionsStylist = onCreateButtonActionsStylist();
2734e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        onProvideFragmentTransitions();
2744e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
2754e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
2764e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
2774e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Creates the presenter used to style the guidance panel. The default implementation returns
2784e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * a basic GuidanceStylist.
2794e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The GuidanceStylist used in this fragment.
2804e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
2814e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public GuidanceStylist onCreateGuidanceStylist() {
2824e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return new GuidanceStylist();
2834e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
2844e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
2854e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
2864e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Creates the presenter used to style the guided actions panel. The default implementation
2874e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * returns a basic GuidedActionsStylist.
2884e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The GuidedActionsStylist used in this fragment.
2894e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
2904e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public GuidedActionsStylist onCreateActionsStylist() {
2914e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return new GuidedActionsStylist();
2924e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
2934e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
2944e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
295d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Creates the presenter used to style a sided actions panel for button only.
296d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * The default implementation returns a basic GuidedActionsStylist.
297d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return The GuidedActionsStylist used in this fragment.
298d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
299d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public GuidedActionsStylist onCreateButtonActionsStylist() {
300be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        GuidedActionsStylist stylist = new GuidedActionsStylist();
301be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        stylist.setAsButtonActions();
302be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return stylist;
303d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
304d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
305d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
3064e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the theme used for styling the fragment. The default returns -1, indicating that the
3074e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * host Activity's theme should be used.
3084e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The theme resource ID of the theme to use in this fragment, or -1 to use the
3094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * host Activity's theme.
3104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
3114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public int onProvideTheme() {
3124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return -1;
3134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
3144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
3154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
3164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the information required to provide guidance to the user. This hook is called during
3174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * {@link #onCreateView}.  May be overridden to return a custom subclass of {@link
3184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * GuidanceStylist.Guidance} for use in a subclass of {@link GuidanceStylist}. The default
3194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * returns a Guidance object with empty fields; subclasses should override.
3204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param savedInstanceState The saved instance state from onCreateView.
3214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The Guidance object representing the information used to guide the user.
3224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
3234e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public @NonNull Guidance onCreateGuidance(Bundle savedInstanceState) {
3244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return new Guidance("", "", "", null);
3254e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
3264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
3274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
3284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Fills out the set of actions available to the user. This hook is called during {@link
3294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * #onCreate}. The default leaves the list of actions empty; subclasses should override.
3304e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param actions A non-null, empty list ready to be populated.
3314e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param savedInstanceState The saved instance state from onCreate.
3324e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
3334e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
3344e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
3354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
3364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
337d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Fills out the set of actions shown at right available to the user. This hook is called during
338d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * {@link #onCreate}. The default leaves the list of actions empty; subclasses may override.
339d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param actions A non-null, empty list ready to be populated.
340d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param savedInstanceState The saved instance state from onCreate.
341d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
342d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void onCreateButtonActions(@NonNull List<GuidedAction> actions,
343d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            Bundle savedInstanceState) {
344d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
345d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
346d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
3474e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Callback invoked when an action is taken by the user. Subclasses should override in
3484e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * order to act on the user's decisions.
3494e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param action The chosen action.
3504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
3514e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void onGuidedActionClicked(GuidedAction action) {
3524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
3534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
3544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
355be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Callback invoked when an action in sub actions is taken by the user. Subclasses should
356be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * override in order to act on the user's decisions.  Default return value is true to close
357be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * the sub actions list.
358be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @param action The chosen action.
359be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return true to collapse the sub actions list, false to keep it expanded.
360be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
361be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public boolean onSubGuidedActionClicked(GuidedAction action) {
362be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return true;
363be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
364be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
365be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
366be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return True if the sub actions list is expanded, false otherwise.
367be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
368be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public boolean isSubActionsExpanded() {
369be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mActionsStylist.isSubActionsExpanded();
370be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
371be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
372be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
373be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Expand a given action's sub actions list.
374be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @param action GuidedAction to expand.
375be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @see GuidedAction#getSubActions()
376be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
377be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public void expandSubActions(GuidedAction action) {
378be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final int actionPosition = mActions.indexOf(action);
379be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (actionPosition < 0) {
380be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            return;
381be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
382be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mActionsStylist.getActionsGridView().setSelectedPositionSmooth(actionPosition,
383be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                new ViewHolderTask() {
384be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            @Override
385be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            public void run(RecyclerView.ViewHolder vh) {
386be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder) vh;
387be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                mActionsStylist.setExpandedViewHolder(avh);
388be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
389be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        });
390be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
391be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
392be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
393be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Collapse sub actions list.
394be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @see GuidedAction#getSubActions()
395be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
396be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public void collapseSubActions() {
397be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mActionsStylist.setExpandedViewHolder(null);
398be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
399be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
400be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
4014e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Callback invoked when an action is focused (made to be the current selection) by the user.
4024e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
4034e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    @Override
4044e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void onGuidedActionFocused(GuidedAction action) {
4054e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
4064e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
4074e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
408bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu     * Callback invoked when an action's title or description has been edited, this happens either
409bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu     * when user clicks confirm button in IME or user closes IME window by BACK key.
41016ab389e0bd11594059f8164a1477045ee625154Dake Gu     * @deprecated Override {@link #onGuidedActionEditedAndProceed(GuidedAction)} and/or
41116ab389e0bd11594059f8164a1477045ee625154Dake Gu     *             {@link #onGuidedActionEditCanceled(GuidedAction)}.
4124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
41316ab389e0bd11594059f8164a1477045ee625154Dake Gu    @Deprecated
4144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void onGuidedActionEdited(GuidedAction action) {
4154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
4164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
4174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
41816ab389e0bd11594059f8164a1477045ee625154Dake Gu     * Callback invoked when an action has been canceled editing, for example when user closes
41916ab389e0bd11594059f8164a1477045ee625154Dake Gu     * IME window by BACK key.  Default implementation calls deprecated method
42016ab389e0bd11594059f8164a1477045ee625154Dake Gu     * {@link #onGuidedActionEdited(GuidedAction)}.
42116ab389e0bd11594059f8164a1477045ee625154Dake Gu     * @param action The action which has been canceled editing.
42216ab389e0bd11594059f8164a1477045ee625154Dake Gu     */
42316ab389e0bd11594059f8164a1477045ee625154Dake Gu    public void onGuidedActionEditCanceled(GuidedAction action) {
42416ab389e0bd11594059f8164a1477045ee625154Dake Gu        onGuidedActionEdited(action);
42516ab389e0bd11594059f8164a1477045ee625154Dake Gu    }
42616ab389e0bd11594059f8164a1477045ee625154Dake Gu
42716ab389e0bd11594059f8164a1477045ee625154Dake Gu    /**
42816ab389e0bd11594059f8164a1477045ee625154Dake Gu     * Callback invoked when an action has been edited, for example when user clicks confirm button
42916ab389e0bd11594059f8164a1477045ee625154Dake Gu     * in IME window.  Default implementation calls deprecated method
430bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu     * {@link #onGuidedActionEdited(GuidedAction)} and returns {@link GuidedAction#ACTION_ID_NEXT}.
431c1741246af607f6be2389056da0182c40f938348Dake Gu     *
432c1741246af607f6be2389056da0182c40f938348Dake Gu     * @param action The action that has been edited.
433c1741246af607f6be2389056da0182c40f938348Dake Gu     * @return ID of the action will be focused or {@link GuidedAction#ACTION_ID_NEXT},
434c1741246af607f6be2389056da0182c40f938348Dake Gu     * {@link GuidedAction#ACTION_ID_CURRENT}.
435c1741246af607f6be2389056da0182c40f938348Dake Gu     */
436c1741246af607f6be2389056da0182c40f938348Dake Gu    public long onGuidedActionEditedAndProceed(GuidedAction action) {
437c1741246af607f6be2389056da0182c40f938348Dake Gu        onGuidedActionEdited(action);
438c1741246af607f6be2389056da0182c40f938348Dake Gu        return GuidedAction.ACTION_ID_NEXT;
439c1741246af607f6be2389056da0182c40f938348Dake Gu    }
440c1741246af607f6be2389056da0182c40f938348Dake Gu
441c1741246af607f6be2389056da0182c40f938348Dake Gu    /**
4424e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Adds the specified GuidedStepSupportFragment to the fragment stack, replacing any existing
4434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * GuidedStepSupportFragments in the stack, and configuring the fragment-to-fragment custom
444bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu     * transitions.  A backstack entry is added, so the fragment will be dismissed when BACK key
445bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu     * is pressed.
446517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_REPLACE}
4474e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <li>If current fragment on stack is not GuidedStepSupportFragment: assign {@link #UI_STYLE_ENTRANCE}
4484e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <p>
4494e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Note: currently fragments added using this method must be created programmatically rather
4504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * than via XML.
4514e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param fragmentManager The FragmentManager to be used in the transaction.
4524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param fragment The GuidedStepSupportFragment to be inserted into the fragment stack.
45368a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * @return The ID returned by the call FragmentTransaction.commit.
4544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
4554e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static int add(FragmentManager fragmentManager, GuidedStepSupportFragment fragment) {
4564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return add(fragmentManager, fragment, android.R.id.content);
4574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
4584e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
4594e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
4604e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Adds the specified GuidedStepSupportFragment to the fragment stack, replacing any existing
4614e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * GuidedStepSupportFragments in the stack, and configuring the fragment-to-fragment custom
462bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu     * transitions.  A backstack entry is added, so the fragment will be dismissed when BACK key
463bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu     * is pressed.
464517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_REPLACE} and
4650b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * {@link #onAddSharedElementTransition(FragmentTransaction, GuidedStepSupportFragment)} will be called
4660b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * to perform shared element transition between GuidedStepSupportFragments.
4674e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <li>If current fragment on stack is not GuidedStepSupportFragment: assign {@link #UI_STYLE_ENTRANCE}
4684e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <p>
4694e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Note: currently fragments added using this method must be created programmatically rather
4704e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * than via XML.
4714e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param fragmentManager The FragmentManager to be used in the transaction.
4724e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param fragment The GuidedStepSupportFragment to be inserted into the fragment stack.
4734e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param id The id of container to add GuidedStepSupportFragment, can be android.R.id.content.
47468a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * @return The ID returned by the call FragmentTransaction.commit.
4754e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
4764e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static int add(FragmentManager fragmentManager, GuidedStepSupportFragment fragment, int id) {
4770b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu        GuidedStepSupportFragment current = getCurrentGuidedStepSupportFragment(fragmentManager);
4780b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu        boolean inGuidedStep = current != null;
479e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu        if (IS_FRAMEWORK_FRAGMENT && Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23
480e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu                && !inGuidedStep) {
481e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu            // workaround b/22631964 for framework fragment
482e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu            fragmentManager.beginTransaction()
483e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu                .replace(id, new DummyFragment(), TAG_LEAN_BACK_ACTIONS_FRAGMENT)
484e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu                .commit();
485e9401be71ad141fe76dc6064c58f8c64054fde8dDake Gu        }
4864e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        FragmentTransaction ft = fragmentManager.beginTransaction();
4874e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
488517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        fragment.setUiStyle(inGuidedStep ? UI_STYLE_REPLACE : UI_STYLE_ENTRANCE);
48937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        ft.addToBackStack(fragment.generateStackEntryName());
4900b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu        if (current != null) {
4910b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            fragment.onAddSharedElementTransition(ft, current);
4920b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu        }
4934e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
4944e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
4954e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
4964e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
497517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_REPLACE} (aka
498517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * when the GuidedStepSupportFragment replacing an existing GuidedStepSupportFragment). Default implementation
499517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * establishes connections between action background views to morph action background bounds
500517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * change from disappearing GuidedStepSupportFragment into this GuidedStepSupportFragment. The default
5010b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * implementation heavily relies on {@link GuidedActionsStylist}'s layout, app may override this
5020b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * method when modifying the default layout of {@link GuidedActionsStylist}.
503517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     *
5040b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * @see GuidedActionsStylist
5050b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * @see #onProvideFragmentTransitions()
5060b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * @param ft The FragmentTransaction to add shared element.
5070b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * @param disappearing The disappearing fragment.
5080b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     */
5090b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    protected void onAddSharedElementTransition(FragmentTransaction ft, GuidedStepSupportFragment
5100b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            disappearing) {
5118bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        View fragmentView = disappearing.getView();
5128bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5130b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                R.id.action_fragment_root), "action_fragment_root");
5148bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5150b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                R.id.action_fragment_background), "action_fragment_background");
5168bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5170b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                R.id.action_fragment), "action_fragment");
5188bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5190b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                R.id.guidedactions_root), "guidedactions_root");
5208bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5218e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu                R.id.guidedactions_content), "guidedactions_content");
5228bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5238e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu                R.id.guidedactions_list_background), "guidedactions_list_background");
5248bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5250b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                R.id.guidedactions_root2), "guidedactions_root2");
5268bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5278e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu                R.id.guidedactions_content2), "guidedactions_content2");
5288bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        addNonNullSharedElementTransition(ft, fragmentView.findViewById(
5298e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu                R.id.guidedactions_list_background2), "guidedactions_list_background2");
5300b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    }
5310b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu
5328bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri    private static void addNonNullSharedElementTransition (FragmentTransaction ft, View subView,
5338bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri                                                           String transitionName)
5348bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri    {
5358bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri        if (subView != null)
5368bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri            TransitionHelper.addSharedElement(ft, subView, transitionName);
5378bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri    }
5388bfa8f6a659c1188a955ee185b13e777d29fb4d9Keyvan Amiri
5390b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    /**
54037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * Returns BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
54137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * associated.  Note {@link #UI_STYLE_ACTIVITY_ROOT} will return empty String.  The method
54237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * returns undefined value if the fragment is not in FragmentManager.
54337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @return BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
54437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * associated.
54537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     */
546fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu    String generateStackEntryName() {
54737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        return generateStackEntryName(getUiStyle(), getClass());
54837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    }
54937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
55037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    /**
55137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * Generates BackStackEntry name for GuidedStepSupportFragment class or empty String if no entry is
55237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * associated.  Note {@link #UI_STYLE_ACTIVITY_ROOT} is not allowed and returns empty String.
553517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @param uiStyle {@link #UI_STYLE_REPLACE} or {@link #UI_STYLE_ENTRANCE}
55437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @return BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
55537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * associated.
55637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     */
557fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu    static String generateStackEntryName(int uiStyle, Class guidedStepFragmentClass) {
55837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        if (!GuidedStepSupportFragment.class.isAssignableFrom(guidedStepFragmentClass)) {
55937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            return "";
56037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        }
56137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        switch (uiStyle) {
562517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        case UI_STYLE_REPLACE:
563517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            return ENTRY_NAME_REPLACE + guidedStepFragmentClass.getName();
56437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        case UI_STYLE_ENTRANCE:
56537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            return ENTRY_NAME_ENTRANCE + guidedStepFragmentClass.getName();
56637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        case UI_STYLE_ACTIVITY_ROOT:
56737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        default:
56837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            return "";
56937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        }
57037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    }
57137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
57237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    /**
573fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * Returns true if the backstack entry represents GuidedStepSupportFragment with
574fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * {@link #UI_STYLE_ENTRANCE}, i.e. this is the first GuidedStepSupportFragment pushed to stack; false
575fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * otherwise.
576fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu     * @see #generateStackEntryName(int, Class)
57737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @param backStackEntryName Name of BackStackEntry.
57837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @return True if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_ENTRANCE};
57937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * false otherwise.
58037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     */
581fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu    static boolean isStackEntryUiStyleEntrance(String backStackEntryName) {
58237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE);
58337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    }
58437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
58537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    /**
58637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * Extract Class name from BackStackEntry name.
58737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @param backStackEntryName Name of BackStackEntry.
58837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @return Class name of GuidedStepSupportFragment.
58937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     */
590fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu    static String getGuidedStepSupportFragmentClassName(String backStackEntryName) {
591517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        if (backStackEntryName.startsWith(ENTRY_NAME_REPLACE)) {
592517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            return backStackEntryName.substring(ENTRY_NAME_REPLACE.length());
59337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        } else if (backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE)) {
59437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            return backStackEntryName.substring(ENTRY_NAME_ENTRANCE.length());
59537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        } else {
59637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            return "";
59737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        }
59837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    }
59937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
60037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    /**
601bd0afce433ec8c219627522a5233d61bf27f7397Dake Gu     * Adds the specified GuidedStepSupportFragment as content of Activity; no backstack entry is added so
60268a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * the activity will be dismissed when BACK key is pressed.  The method is typically called in
60368a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * Activity.onCreate() when savedInstanceState is null.  When savedInstanceState is not null,
60468a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * the Activity is being restored,  do not call addAsRoot() to duplicate the Fragment restored
60568a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * by FragmentManager.
6064e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * {@link #UI_STYLE_ACTIVITY_ROOT} is assigned.
6074e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     *
6084e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Note: currently fragments added using this method must be created programmatically rather
6094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * than via XML.
6104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param activity The Activity to be used to insert GuidedstepFragment.
6114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param fragment The GuidedStepSupportFragment to be inserted into the fragment stack.
6124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param id The id of container to add GuidedStepSupportFragment, can be android.R.id.content.
61368a94e5c24b85f071fb57727954510fff0224d9cDake Gu     * @return The ID returned by the call FragmentTransaction.commit, or -1 there is already
61468a94e5c24b85f071fb57727954510fff0224d9cDake Gu     *         GuidedStepSupportFragment.
6154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
6164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static int addAsRoot(FragmentActivity activity, GuidedStepSupportFragment fragment, int id) {
6174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // Workaround b/23764120: call getDecorView() to force requestFeature of ActivityTransition.
6184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        activity.getWindow().getDecorView();
6194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        FragmentManager fragmentManager = activity.getSupportFragmentManager();
62068a94e5c24b85f071fb57727954510fff0224d9cDake Gu        if (fragmentManager.findFragmentByTag(TAG_LEAN_BACK_ACTIONS_FRAGMENT) != null) {
62168a94e5c24b85f071fb57727954510fff0224d9cDake Gu            Log.w(TAG, "Fragment is already exists, likely calling " +
62268a94e5c24b85f071fb57727954510fff0224d9cDake Gu                    "addAsRoot() when savedInstanceState is not null in Activity.onCreate().");
62368a94e5c24b85f071fb57727954510fff0224d9cDake Gu            return -1;
62468a94e5c24b85f071fb57727954510fff0224d9cDake Gu        }
6254e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        FragmentTransaction ft = fragmentManager.beginTransaction();
6264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        fragment.setUiStyle(UI_STYLE_ACTIVITY_ROOT);
6274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
6284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
6294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
6304e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
6314e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the current GuidedStepSupportFragment on the fragment transaction stack.
6324e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The current GuidedStepSupportFragment, if any, on the fragment transaction stack.
6334e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
6344e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public static GuidedStepSupportFragment getCurrentGuidedStepSupportFragment(FragmentManager fm) {
6354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        Fragment f = fm.findFragmentByTag(TAG_LEAN_BACK_ACTIONS_FRAGMENT);
6364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (f instanceof GuidedStepSupportFragment) {
6374e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            return (GuidedStepSupportFragment) f;
6384e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
6394e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return null;
6404e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
6414e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
6424e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
6434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the GuidanceStylist that displays guidance information for the user.
6444e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The GuidanceStylist for this fragment.
6454e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
6464e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public GuidanceStylist getGuidanceStylist() {
6474e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return mGuidanceStylist;
6484e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
6494e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
6504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
6514e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the GuidedActionsStylist that displays the actions the user may take.
6524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The GuidedActionsStylist for this fragment.
6534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
6544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public GuidedActionsStylist getGuidedActionsStylist() {
6554e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return mActionsStylist;
6564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
6574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
6584e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
659d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Returns the list of button GuidedActions that the user may take in this fragment.
660d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return The list of button GuidedActions for this fragment.
661d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
662d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public List<GuidedAction> getButtonActions() {
663d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return mButtonActions;
664d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
665d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
666d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
667d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Find button GuidedAction by Id.
668d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param id  Id of the button action to search.
669d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return  GuidedAction object or null if not found.
670d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
671d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public GuidedAction findButtonActionById(long id) {
672d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        int index = findButtonActionPositionById(id);
673d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return index >= 0 ? mButtonActions.get(index) : null;
674d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
675d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
676d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
677d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Find button GuidedAction position in array by Id.
678d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param id  Id of the button action to search.
679d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return  position of GuidedAction object in array or -1 if not found.
680d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
681d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public int findButtonActionPositionById(long id) {
682d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        if (mButtonActions != null) {
683d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            for (int i = 0; i < mButtonActions.size(); i++) {
684d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                GuidedAction action = mButtonActions.get(i);
685d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                if (mButtonActions.get(i).getId() == id) {
686d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                    return i;
687d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                }
688d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            }
689d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        }
690d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return -1;
691d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
692d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
693d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
694d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Returns the GuidedActionsStylist that displays the button actions the user may take.
695d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return The GuidedActionsStylist for this fragment.
696d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
697d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public GuidedActionsStylist getGuidedButtonActionsStylist() {
698d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return mButtonActionsStylist;
699d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
700d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
701d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
702d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Sets the list of button GuidedActions that the user may take in this fragment.
703d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param actions The list of button GuidedActions for this fragment.
704d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
705d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void setButtonActions(List<GuidedAction> actions) {
706d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mButtonActions = actions;
707d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        if (mButtonAdapter != null) {
708d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            mButtonAdapter.setActions(mButtonActions);
709d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        }
710d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
711d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
712d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
713d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Notify an button action has changed and update its UI.
714d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param position Position of the button GuidedAction in array.
715d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
716d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void notifyButtonActionChanged(int position) {
717d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        if (mButtonAdapter != null) {
718d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            mButtonAdapter.notifyItemChanged(position);
719d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        }
720d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
721d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
722d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
723d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Returns the view corresponding to the button action at the indicated position in the list of
724d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * actions for this fragment.
725d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param position The integer position of the button action of interest.
726d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return The View corresponding to the button action at the indicated position, or null if
727d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * that action is not currently onscreen.
728d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
729d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public View getButtonActionItemView(int position) {
730d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        final RecyclerView.ViewHolder holder = mButtonActionsStylist.getActionsGridView()
731d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                    .findViewHolderForPosition(position);
732d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return holder == null ? null : holder.itemView;
733d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
734d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
735d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
736d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Scrolls the action list to the position indicated, selecting that button action's view.
737d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @param position The integer position of the button action of interest.
738d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
739d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void setSelectedButtonActionPosition(int position) {
740d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mButtonActionsStylist.getActionsGridView().setSelectedPosition(position);
741d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
742d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
743d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
744d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Returns the position if the currently selected button GuidedAction.
745d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * @return position The integer position of the currently selected button action.
746d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
747d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public int getSelectedButtonActionPosition() {
748d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return mButtonActionsStylist.getActionsGridView().getSelectedPosition();
749d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
750d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
751d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
7524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the list of GuidedActions that the user may take in this fragment.
7534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The list of GuidedActions for this fragment.
7544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
7554e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public List<GuidedAction> getActions() {
7564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return mActions;
7574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
7584e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
7594e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
760c1741246af607f6be2389056da0182c40f938348Dake Gu     * Find GuidedAction by Id.
761c1741246af607f6be2389056da0182c40f938348Dake Gu     * @param id  Id of the action to search.
762c1741246af607f6be2389056da0182c40f938348Dake Gu     * @return  GuidedAction object or null if not found.
763c1741246af607f6be2389056da0182c40f938348Dake Gu     */
764c1741246af607f6be2389056da0182c40f938348Dake Gu    public GuidedAction findActionById(long id) {
765c1741246af607f6be2389056da0182c40f938348Dake Gu        int index = findActionPositionById(id);
766c1741246af607f6be2389056da0182c40f938348Dake Gu        return index >= 0 ? mActions.get(index) : null;
767c1741246af607f6be2389056da0182c40f938348Dake Gu    }
768c1741246af607f6be2389056da0182c40f938348Dake Gu
769c1741246af607f6be2389056da0182c40f938348Dake Gu    /**
770c1741246af607f6be2389056da0182c40f938348Dake Gu     * Find GuidedAction position in array by Id.
771c1741246af607f6be2389056da0182c40f938348Dake Gu     * @param id  Id of the action to search.
772c1741246af607f6be2389056da0182c40f938348Dake Gu     * @return  position of GuidedAction object in array or -1 if not found.
773c1741246af607f6be2389056da0182c40f938348Dake Gu     */
774c1741246af607f6be2389056da0182c40f938348Dake Gu    public int findActionPositionById(long id) {
775c1741246af607f6be2389056da0182c40f938348Dake Gu        if (mActions != null) {
776c1741246af607f6be2389056da0182c40f938348Dake Gu            for (int i = 0; i < mActions.size(); i++) {
777c1741246af607f6be2389056da0182c40f938348Dake Gu                GuidedAction action = mActions.get(i);
778c1741246af607f6be2389056da0182c40f938348Dake Gu                if (mActions.get(i).getId() == id) {
779c1741246af607f6be2389056da0182c40f938348Dake Gu                    return i;
780c1741246af607f6be2389056da0182c40f938348Dake Gu                }
781c1741246af607f6be2389056da0182c40f938348Dake Gu            }
782c1741246af607f6be2389056da0182c40f938348Dake Gu        }
783c1741246af607f6be2389056da0182c40f938348Dake Gu        return -1;
784c1741246af607f6be2389056da0182c40f938348Dake Gu    }
785c1741246af607f6be2389056da0182c40f938348Dake Gu
786c1741246af607f6be2389056da0182c40f938348Dake Gu    /**
7874e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Sets the list of GuidedActions that the user may take in this fragment.
7884e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param actions The list of GuidedActions for this fragment.
7894e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
7904e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void setActions(List<GuidedAction> actions) {
7914e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        mActions = actions;
7924e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (mAdapter != null) {
7934e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            mAdapter.setActions(mActions);
7944e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
7954e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
7964e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
7974e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
798c1741246af607f6be2389056da0182c40f938348Dake Gu     * Notify an action has changed and update its UI.
799c1741246af607f6be2389056da0182c40f938348Dake Gu     * @param position Position of the GuidedAction in array.
800c1741246af607f6be2389056da0182c40f938348Dake Gu     */
801c1741246af607f6be2389056da0182c40f938348Dake Gu    public void notifyActionChanged(int position) {
802c1741246af607f6be2389056da0182c40f938348Dake Gu        if (mAdapter != null) {
803c1741246af607f6be2389056da0182c40f938348Dake Gu            mAdapter.notifyItemChanged(position);
804c1741246af607f6be2389056da0182c40f938348Dake Gu        }
805c1741246af607f6be2389056da0182c40f938348Dake Gu    }
806c1741246af607f6be2389056da0182c40f938348Dake Gu
807c1741246af607f6be2389056da0182c40f938348Dake Gu    /**
8084e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the view corresponding to the action at the indicated position in the list of
8094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * actions for this fragment.
8104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param position The integer position of the action of interest.
8114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return The View corresponding to the action at the indicated position, or null if that
8124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * action is not currently onscreen.
8134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
8144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public View getActionItemView(int position) {
815d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        final RecyclerView.ViewHolder holder = mActionsStylist.getActionsGridView()
816d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                    .findViewHolderForPosition(position);
817d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return holder == null ? null : holder.itemView;
8184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
8194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
8204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
8214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Scrolls the action list to the position indicated, selecting that action's view.
8224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @param position The integer position of the action of interest.
8234e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
8244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void setSelectedActionPosition(int position) {
825d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mActionsStylist.getActionsGridView().setSelectedPosition(position);
8264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
8274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
8284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
8294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * Returns the position if the currently selected GuidedAction.
8304e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * @return position The integer position of the currently selected action.
8314e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
8324e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public int getSelectedActionPosition() {
833d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        return mActionsStylist.getActionsGridView().getSelectedPosition();
8344e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
8354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
8364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
8370b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * Called by Constructor to provide fragment transitions.  The default implementation assigns
8380b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * transitions based on {@link #getUiStyle()}:
8390b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * <ul>
840517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * <li> {@link #UI_STYLE_REPLACE} Slide from/to end(right) for enter transition, slide from/to
8410b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * start(left) for exit transition, shared element enter transition is set to ChangeBounds.
8420b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * <li> {@link #UI_STYLE_ENTRANCE} Enter transition is set to slide from both sides, exit
843517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * transition is same as {@link #UI_STYLE_REPLACE}, no shared element enter transition.
8440b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * <li> {@link #UI_STYLE_ACTIVITY_ROOT} Enter transition is set to null and app should rely on
845517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * activity transition, exit transition is same as {@link #UI_STYLE_REPLACE}, no shared element
8460b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * enter transition.
8470b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * </ul>
8480b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * <p>
8490b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * The default implementation heavily relies on {@link GuidedActionsStylist} and
8500b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * {@link GuidanceStylist} layout, app may override this method when modifying the default
8510b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * layout of {@link GuidedActionsStylist} or {@link GuidanceStylist}.
8524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * <p>
8530b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * TIP: because the fragment view is removed during fragment transition, in general app cannot
8540b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * use two Visibility transition together. Workaround is to create your own Visibility
8550b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * transition that controls multiple animators (e.g. slide and fade animation in one Transition
8560b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     * class).
8574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
8584e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    protected void onProvideFragmentTransitions() {
8594e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (Build.VERSION.SDK_INT >= 21) {
860517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            final int uiStyle = getUiStyle();
861517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            if (uiStyle == UI_STYLE_REPLACE) {
8628403619efebe94666c0615c3fc85080a303acf80Dake Gu                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
863517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu                TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true);
8648403619efebe94666c0615c3fc85080a303acf80Dake Gu                TransitionHelper.setEnterTransition(this, enterTransition);
865517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu
866517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu                Object changeBounds = TransitionHelper.createChangeBounds(false);
867517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu                TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
868517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            } else if (uiStyle == UI_STYLE_ENTRANCE) {
869e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                if (entranceTransitionType == SLIDE_FROM_SIDE) {
870e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
871e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                            TransitionHelper.FADE_OUT);
872e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.include(fade, R.id.guidedstep_background);
873e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    Object slideFromSide = TransitionHelper.createFadeAndShortSlide(Gravity.END | Gravity.START);
874e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.include(slideFromSide, R.id.content_fragment);
875e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.include(slideFromSide, R.id.action_fragment_root);
876e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    Object enterTransition = TransitionHelper.createTransitionSet(false);
877e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.addTransition(enterTransition, fade);
878e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.addTransition(enterTransition, slideFromSide);
879e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.setEnterTransition(this, enterTransition);
880e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                } else {
881e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    Object slideFromBottom = TransitionHelper.createFadeAndShortSlide(Gravity.BOTTOM);
882e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.include(slideFromBottom, R.id.guidedstep_background_view_root);
883e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    Object enterTransition = TransitionHelper.createTransitionSet(false);
884e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.addTransition(enterTransition, slideFromBottom);
885e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                    TransitionHelper.setEnterTransition(this, enterTransition);
886e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata                }
8870b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                // No shared element transition
8880b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                TransitionHelper.setSharedElementEnterTransition(this, null);
889517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            } else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) {
8904e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                // for Activity root, we dont need enter transition, use activity transition
8918403619efebe94666c0615c3fc85080a303acf80Dake Gu                TransitionHelper.setEnterTransition(this, null);
8920b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                // No shared element transition
8930b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                TransitionHelper.setSharedElementEnterTransition(this, null);
8944e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            }
8958e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu            // exitTransition is same for all style
8968e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu            Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
8978e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu            TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true);
8988e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu            TransitionHelper.setExitTransition(this, exitTransition);
8994e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
9004e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
9014e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
9024e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
903517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Called by onCreateView to inflate background view.  Default implementation loads view
904517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * from {@link R.layout#lb_guidedstep_background} which holds a reference to
905517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * guidedStepBackground.
906517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @param inflater LayoutInflater to load background view.
907517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @param container Parent view of background view.
908517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @param savedInstanceState
909517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @return Created background view or null if no background.
9104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
911517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu    public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
912517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu            Bundle savedInstanceState) {
913517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
9144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
9154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
9164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
917517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Set UI style to fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when fragment
918517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * is first initialized. UI style is used to choose different fragment transition animations and
919517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * determine if this is the first GuidedStepSupportFragment on backstack. In most cases app does not
920517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * directly call this method, app calls helper function
921517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * {@link #add(FragmentManager, GuidedStepSupportFragment, int)}. However if the app creates Fragment
922517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * transaction and controls backstack by itself, it would need call setUiStyle() to select the
923517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * fragment transition to use.
9244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     *
925517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
926517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     *        {@link #UI_STYLE_ENTRANCE}.
9274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
9284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void setUiStyle(int style) {
9294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        int oldStyle = getUiStyle();
9304e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        Bundle arguments = getArguments();
931fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu        boolean isNew = false;
9324e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (arguments == null) {
9334e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            arguments = new Bundle();
934fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu            isNew = true;
9354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
9364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        arguments.putInt(EXTRA_UI_STYLE, style);
9374e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // call setArgument() will validate if the fragment is already added.
938fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu        if (isNew) {
939fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu            setArguments(arguments);
940fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu        }
9414e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (style != oldStyle) {
9424e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            onProvideFragmentTransitions();
9434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
9444e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
9454e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
9464e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
947517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Read UI style from fragment arguments.  Default value is {@link #UI_STYLE_ENTRANCE} when
948517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * fragment is first initialized.  UI style is used to choose different fragment transition
949517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * animations and determine if this is the first GuidedStepSupportFragment on backstack.
9504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     *
951517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
9524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * {@link #UI_STYLE_ENTRANCE}.
953517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * @see #onProvideFragmentTransitions()
9544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
9554e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public int getUiStyle() {
9564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        Bundle b = getArguments();
957517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        if (b == null) return UI_STYLE_ENTRANCE;
958517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        return b.getInt(EXTRA_UI_STYLE, UI_STYLE_ENTRANCE);
9594e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
9604e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
9614e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
9624e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * {@inheritDoc}
9634e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
9644e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    @Override
9654e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void onCreate(Bundle savedInstanceState) {
9664e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        super.onCreate(savedInstanceState);
9674e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (DEBUG) Log.v(TAG, "onCreate");
9684e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // Set correct transition from saved arguments.
9694e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        onProvideFragmentTransitions();
9704e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        Bundle state = (savedInstanceState != null) ? savedInstanceState : getArguments();
9714e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (state != null) {
9724e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            if (mSelectedIndex == -1) {
9734e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                mSelectedIndex = state.getInt(EXTRA_ACTION_SELECTED_INDEX, -1);
9744e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            }
9754e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
976d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        ArrayList<GuidedAction> actions = new ArrayList<GuidedAction>();
977d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        onCreateActions(actions, savedInstanceState);
9789050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        if (savedInstanceState != null) {
9799050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            onRestoreActions(actions, savedInstanceState);
9809050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        }
981d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        setActions(actions);
982d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        ArrayList<GuidedAction> buttonActions = new ArrayList<GuidedAction>();
983d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        onCreateButtonActions(buttonActions, savedInstanceState);
9849050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        if (savedInstanceState != null) {
9859050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            onRestoreButtonActions(buttonActions, savedInstanceState);
9869050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        }
987d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        setButtonActions(buttonActions);
988d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
989d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
990d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
991d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * {@inheritDoc}
992d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
993d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    @Override
994d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void onDestroyView() {
995d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mGuidanceStylist.onDestroyView();
996d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mActionsStylist.onDestroyView();
997d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mButtonActionsStylist.onDestroyView();
99843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mAdapter = null;
999be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mSubAdapter =  null;
100043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mButtonAdapter = null;
100143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mAdapterGroup = null;
1002d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        super.onDestroyView();
10034e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
10044e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
10054e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
10064e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * {@inheritDoc}
10074e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
10084e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    @Override
10094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public View onCreateView(LayoutInflater inflater, ViewGroup container,
10104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            Bundle savedInstanceState) {
10114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (DEBUG) Log.v(TAG, "onCreateView");
10124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
10134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        resolveTheme();
10144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        inflater = getThemeInflater(inflater);
10154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
1016b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu        GuidedStepRootLayout root = (GuidedStepRootLayout) inflater.inflate(
1017b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu                R.layout.lb_guidedstep_fragment, container, false);
101868d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata
1019b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu        root.setFocusOutStart(isFocusOutStartAllowed());
1020b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu        root.setFocusOutEnd(isFocusOutEndAllowed());
102168d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata
1022517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        ViewGroup guidanceContainer = (ViewGroup) root.findViewById(R.id.content_fragment);
1023517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        ViewGroup actionContainer = (ViewGroup) root.findViewById(R.id.action_fragment);
10244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
10254e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        Guidance guidance = onCreateGuidance(savedInstanceState);
10264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        View guidanceView = mGuidanceStylist.onCreateView(inflater, guidanceContainer, guidance);
10274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        guidanceContainer.addView(guidanceView);
10284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
10294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        View actionsView = mActionsStylist.onCreateView(inflater, actionContainer);
10304e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        actionContainer.addView(actionsView);
10314e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
1032d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        View buttonActionsView = mButtonActionsStylist.onCreateView(inflater, actionContainer);
1033d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        actionContainer.addView(buttonActionsView);
1034d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
10354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        GuidedActionAdapter.EditListener editListener = new GuidedActionAdapter.EditListener() {
1036c1741246af607f6be2389056da0182c40f938348Dake Gu
10374e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                @Override
1038c1741246af607f6be2389056da0182c40f938348Dake Gu                public void onImeOpen() {
1039c1741246af607f6be2389056da0182c40f938348Dake Gu                    runImeAnimations(true);
1040c1741246af607f6be2389056da0182c40f938348Dake Gu                }
1041c1741246af607f6be2389056da0182c40f938348Dake Gu
1042c1741246af607f6be2389056da0182c40f938348Dake Gu                @Override
1043c1741246af607f6be2389056da0182c40f938348Dake Gu                public void onImeClose() {
1044c1741246af607f6be2389056da0182c40f938348Dake Gu                    runImeAnimations(false);
1045c1741246af607f6be2389056da0182c40f938348Dake Gu                }
1046c1741246af607f6be2389056da0182c40f938348Dake Gu
1047c1741246af607f6be2389056da0182c40f938348Dake Gu                @Override
1048bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu                public long onGuidedActionEditedAndProceed(GuidedAction action) {
1049c1741246af607f6be2389056da0182c40f938348Dake Gu                    return GuidedStepSupportFragment.this.onGuidedActionEditedAndProceed(action);
10504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                }
1051bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu
1052bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu                @Override
105316ab389e0bd11594059f8164a1477045ee625154Dake Gu                public void onGuidedActionEditCanceled(GuidedAction action) {
105416ab389e0bd11594059f8164a1477045ee625154Dake Gu                    GuidedStepSupportFragment.this.onGuidedActionEditCanceled(action);
1055bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu                }
10564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        };
10574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
1058be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mAdapter = new GuidedActionAdapter(mActions, new GuidedActionAdapter.ClickListener() {
1059be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            @Override
1060be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            public void onGuidedActionClicked(GuidedAction action) {
1061be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                GuidedStepSupportFragment.this.onGuidedActionClicked(action);
1062be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                if (isSubActionsExpanded()) {
1063be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    collapseSubActions();
1064be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                } else if (action.hasSubActions()) {
1065be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    expandSubActions(action);
1066be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                }
1067be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
1068be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }, this, mActionsStylist, false);
1069be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mButtonAdapter =
1070be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                new GuidedActionAdapter(mButtonActions, new GuidedActionAdapter.ClickListener() {
1071be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    @Override
1072be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    public void onGuidedActionClicked(GuidedAction action) {
1073be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                        GuidedStepSupportFragment.this.onGuidedActionClicked(action);
1074be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    }
1075be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                }, this, mButtonActionsStylist, false);
1076be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mSubAdapter = new GuidedActionAdapter(null, new GuidedActionAdapter.ClickListener() {
1077be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            @Override
1078be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            public void onGuidedActionClicked(GuidedAction action) {
10791ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                if (mActionsStylist.isInExpandTransition()) {
10801ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                    return;
10811ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                }
1082be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                if (GuidedStepSupportFragment.this.onSubGuidedActionClicked(action)) {
1083be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    collapseSubActions();
1084be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                }
1085be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
1086be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }, this, mActionsStylist, true);
108743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mAdapterGroup = new GuidedActionAdapterGroup();
1088be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mAdapterGroup.addAdpter(mAdapter, mButtonAdapter);
1089be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mAdapterGroup.addAdpter(mSubAdapter, null);
109043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mAdapterGroup.setEditListener(editListener);
1091b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        mActionsStylist.setEditListener(editListener);
1092d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
1093d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mActionsStylist.getActionsGridView().setAdapter(mAdapter);
1094be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (mActionsStylist.getSubActionsGridView() != null) {
1095be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            mActionsStylist.getSubActionsGridView().setAdapter(mSubAdapter);
1096be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1097d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        mButtonActionsStylist.getActionsGridView().setAdapter(mButtonAdapter);
1098d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        if (mButtonActions.size() == 0) {
10990b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            // when there is no button actions, we dont need show the second panel, but keep
11000b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            // the width zero to run ChangeBounds transition.
11010b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
11020b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu                    buttonActionsView.getLayoutParams();
11030b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            lp.weight = 0;
11040b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            buttonActionsView.setLayoutParams(lp);
1105d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        } else {
11060b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            // when there are two actions panel, we need adjust the weight of action to
11070b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu            // guidedActionContentWidthWeightTwoPanels.
1108d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            Context ctx = mThemeWrapper != null ? mThemeWrapper : getActivity();
1109d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            TypedValue typedValue = new TypedValue();
1110d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            if (ctx.getTheme().resolveAttribute(R.attr.guidedActionContentWidthWeightTwoPanels,
1111d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                    typedValue, true)) {
1112517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu                View actionsRoot = root.findViewById(R.id.action_fragment_root);
1113d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                float weight = typedValue.getFloat();
1114d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) actionsRoot
1115d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                        .getLayoutParams();
1116d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                lp.weight = weight;
1117d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                actionsRoot.setLayoutParams(lp);
1118d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            }
1119d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        }
11204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
11214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        int pos = (mSelectedIndex >= 0 && mSelectedIndex < mActions.size()) ?
11224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                mSelectedIndex : getFirstCheckedAction();
1123d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        setSelectedActionPosition(pos);
1124d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
1125d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu        setSelectedButtonActionPosition(0);
11264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
112768d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata        // Add the background view.
1128517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        View backgroundView = onCreateBackgroundView(inflater, root, savedInstanceState);
1129517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        if (backgroundView != null) {
113068d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata            FrameLayout backgroundViewRoot = (FrameLayout)root.findViewById(
113168d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata                R.id.guidedstep_background_view_root);
113268d693985e85ee5eed18f78beaaadbfd9b8a4f13susnata            backgroundViewRoot.addView(backgroundView, 0);
1133517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        }
1134517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu        return root;
11354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
11364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
11375b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu    @Override
11385b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu    public void onResume() {
11395b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu        super.onResume();
11405b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu        getView().findViewById(R.id.action_fragment).requestFocus();
11415b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu    }
11425b20ee9a8d24e70f5e9f2d134440885241a00586Dake Gu
11434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    /**
11449050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     * Get the key will be used to save GuidedAction with Fragment.
11459050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     * @param action GuidedAction to get key.
11469050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     * @return Key to save the GuidedAction.
11479050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     */
11489050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final String getAutoRestoreKey(GuidedAction action) {
11499050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        return EXTRA_ACTION_PREFIX + action.getId();
11509050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
11519050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
11529050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    /**
11539050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     * Get the key will be used to save GuidedAction with Fragment.
11549050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     * @param action GuidedAction to get key.
11559050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     * @return Key to save the GuidedAction.
11569050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu     */
11579050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final String getButtonAutoRestoreKey(GuidedAction action) {
11589050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        return EXTRA_BUTTON_ACTION_PREFIX + action.getId();
11599050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
11609050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
11619050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final static boolean isSaveEnabled(GuidedAction action) {
11629050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        return action.isAutoSaveRestoreEnabled() && action.getId() != GuidedAction.NO_ID;
11639050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
11649050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
11659050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final void onRestoreActions(List<GuidedAction> actions, Bundle savedInstanceState) {
11669050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        for (int i = 0, size = actions.size(); i < size; i++) {
11679050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            GuidedAction action = actions.get(i);
11689050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            if (isSaveEnabled(action)) {
11699050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu                action.onRestoreInstanceState(savedInstanceState, getAutoRestoreKey(action));
11709050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            }
11719050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        }
11729050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
11739050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
11749050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final void onRestoreButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
11759050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        for (int i = 0, size = actions.size(); i < size; i++) {
11769050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            GuidedAction action = actions.get(i);
11779050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            if (isSaveEnabled(action)) {
11789050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu                action.onRestoreInstanceState(savedInstanceState, getButtonAutoRestoreKey(action));
11799050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            }
11809050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        }
11819050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
11829050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
11839050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final void onSaveActions(List<GuidedAction> actions, Bundle outState) {
11849050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        for (int i = 0, size = actions.size(); i < size; i++) {
11859050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            GuidedAction action = actions.get(i);
11869050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            if (isSaveEnabled(action)) {
11879050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu                action.onSaveInstanceState(outState, getAutoRestoreKey(action));
11889050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            }
11899050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        }
11909050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
11919050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
11929050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    final void onSaveButtonActions(List<GuidedAction> actions, Bundle outState) {
11939050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        for (int i = 0, size = actions.size(); i < size; i++) {
11949050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            GuidedAction action = actions.get(i);
11959050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            if (isSaveEnabled(action)) {
11969050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu                action.onSaveInstanceState(outState, getButtonAutoRestoreKey(action));
11979050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu            }
11989050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        }
11999050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    }
12009050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu
12019050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu    /**
12024e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     * {@inheritDoc}
12034e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu     */
12044e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    @Override
12054e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    public void onSaveInstanceState(Bundle outState) {
12064e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        super.onSaveInstanceState(outState);
12079050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        onSaveActions(mActions, outState);
12089050c0fc8fbcd8ffe794915375efd5d2b96a0b2dDake Gu        onSaveButtonActions(mButtonActions, outState);
12094e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        outState.putInt(EXTRA_ACTION_SELECTED_INDEX,
1210d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                (mActionsStylist.getActionsGridView() != null) ?
1211d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu                        getSelectedActionPosition() : mSelectedIndex);
12124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
12134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
12144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private static boolean isGuidedStepTheme(Context context) {
12154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        int resId = R.attr.guidedStepThemeFlag;
12164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        TypedValue typedValue = new TypedValue();
12174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        boolean found = context.getTheme().resolveAttribute(resId, typedValue, true);
12184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (DEBUG) Log.v(TAG, "Found guided step theme flag? " + found);
12194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return found && typedValue.type == TypedValue.TYPE_INT_BOOLEAN && typedValue.data != 0;
12204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
12214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
122237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    /**
122337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * Convenient method to close GuidedStepSupportFragments on top of other content or finish Activity if
122437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * GuidedStepSupportFragments were started in a separate activity.  Pops all stack entries including
122537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * {@link #UI_STYLE_ENTRANCE}; if {@link #UI_STYLE_ENTRANCE} is not found, finish the activity.
1226517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * Note that this method must be paired with {@link #add(FragmentManager, GuidedStepSupportFragment,
1227517a5ef1716efc7696a78dc9e0fff0312c47612dDake Gu     * int)} which sets up the stack entry name for finding which fragment we need to pop back to.
122837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     */
122937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    public void finishGuidedStepSupportFragments() {
123037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        final FragmentManager fragmentManager = getFragmentManager();
123137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        final int entryCount = fragmentManager.getBackStackEntryCount();
123237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        if (entryCount > 0) {
123337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            for (int i = entryCount - 1; i >= 0; i--) {
123437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
1235fd3fc2de015a0771537ff5100668941eb7c0ea00Dake Gu                if (isStackEntryUiStyleEntrance(entry.getName())) {
1236fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu                    GuidedStepSupportFragment top = getCurrentGuidedStepSupportFragment(fragmentManager);
1237fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu                    if (top != null) {
1238fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu                        top.setUiStyle(UI_STYLE_ENTRANCE);
1239fd23a2faf77c66a405a2b2974f719041feda9177Dake Gu                    }
124037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                    fragmentManager.popBackStack(entry.getId(),
124137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                            FragmentManager.POP_BACK_STACK_INCLUSIVE);
124237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                    return;
124337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                }
124437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            }
124537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        }
124637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        ActivityCompat.finishAfterTransition(getActivity());
124737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    }
124837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
124937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    /**
125037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * Convenient method to pop to fragment with Given class.
125137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @param  guidedStepFragmentClass  Name of the Class of GuidedStepSupportFragment to pop to.
125237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     * @param flags Either 0 or {@link FragmentManager#POP_BACK_STACK_INCLUSIVE}.
125337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu     */
125437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    public void popBackStackToGuidedStepSupportFragment(Class guidedStepFragmentClass, int flags) {
125537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        if (!GuidedStepSupportFragment.class.isAssignableFrom(guidedStepFragmentClass)) {
125637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            return;
125737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        }
125837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        final FragmentManager fragmentManager = getFragmentManager();
125937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        final int entryCount = fragmentManager.getBackStackEntryCount();
126037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        String className = guidedStepFragmentClass.getName();
126137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        if (entryCount > 0) {
126237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            for (int i = entryCount - 1; i >= 0; i--) {
126337d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
126437d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                String entryClassName = getGuidedStepSupportFragmentClassName(entry.getName());
126537d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                if (className.equals(entryClassName)) {
126637d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                    fragmentManager.popBackStack(entry.getId(), flags);
126737d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                    return;
126837d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu                }
126937d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu            }
127037d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu        }
127137d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu    }
127237d4ed50ac446f9f8ad033fe56888dd6eb602d4dDake Gu
1273b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu    /**
1274b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * Returns true if allows focus out of start edge of GuidedStepSupportFragment, false otherwise.
1275b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * Default value is false, the reason is to disable FocusFinder to find focusable views
1276b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * beneath content of GuidedStepSupportFragment.  Subclass may override.
1277b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * @return True if allows focus out of start edge of GuidedStepSupportFragment.
1278b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     */
1279b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu    public boolean isFocusOutStartAllowed() {
1280b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu        return false;
1281b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu    }
1282b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu
1283b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu    /**
1284b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * Returns true if allows focus out of end edge of GuidedStepSupportFragment, false otherwise.
1285b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * Default value is false, the reason is to disable FocusFinder to find focusable views
1286b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * beneath content of GuidedStepSupportFragment.  Subclass may override.
1287b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     * @return True if allows focus out of end edge of GuidedStepSupportFragment.
1288b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu     */
1289b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu    public boolean isFocusOutEndAllowed() {
1290b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu        return false;
1291b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu    }
1292b5ba5532e1ece8fd051ad1066c8efb0d2c32936cDake Gu
1293e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    /**
1294e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * Sets the transition type to be used for {@link #UI_STYLE_ENTRANCE} animation.
1295e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * Currently we provide 2 different variations for animation - slide in from
1296e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * side (default) or bottom.
1297e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     *
1298e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * Ideally we can retireve the screen mode settings from the theme attribute
1299e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * {@code Theme.Leanback.GuidedStep#guidedStepHeightWeight} and use that to
1300e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * determine the transition. But the fragment context to retrieve the theme
1301e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * isn't available on platform v23 or earlier.
1302e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     *
1303e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * For now clients(subclasses) can call this method inside the contructor.
1304e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     * @hide
1305e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata     */
1306e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    public void setEntranceTransitionType(int transitionType) {
1307e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata      this.entranceTransitionType = transitionType;
1308e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata    }
1309e03d465a8a7b3e7c63a3487f2c05b99f28b8bec9susnata
13104e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private void resolveTheme() {
13114e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // Look up the guidedStepTheme in the currently specified theme.  If it exists,
13124e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        // replace the theme with its value.
13134e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        FragmentActivity activity = getActivity();
13144e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (mTheme == -1 && !isGuidedStepTheme(activity)) {
13154e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            // Look up the guidedStepTheme in the activity's currently specified theme.  If it
13164e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            // exists, replace the theme with its value.
13174e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            int resId = R.attr.guidedStepTheme;
13184e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            TypedValue typedValue = new TypedValue();
13194e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            boolean found = activity.getTheme().resolveAttribute(resId, typedValue, true);
13204e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            if (DEBUG) Log.v(TAG, "Found guided step theme reference? " + found);
13214e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            if (found) {
13224e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                ContextThemeWrapper themeWrapper =
13234e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                        new ContextThemeWrapper(activity, typedValue.resourceId);
13244e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                if (isGuidedStepTheme(themeWrapper)) {
13254e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                    mTheme = typedValue.resourceId;
13264e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                    mThemeWrapper = themeWrapper;
13274e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                } else {
13284e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                    found = false;
13294e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                    mThemeWrapper = null;
13304e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                }
13314e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            }
13324e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            if (!found) {
13334e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                Log.e(TAG, "GuidedStepSupportFragment does not have an appropriate theme set.");
13344e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            }
13354e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        } else if (mTheme != -1) {
13364e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            mThemeWrapper = new ContextThemeWrapper(activity, mTheme);
13374e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
13384e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
13394e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
13404e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private LayoutInflater getThemeInflater(LayoutInflater inflater) {
13414e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (mTheme == -1) {
13424e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            return inflater;
13434e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        } else {
13444e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            return inflater.cloneInContext(mThemeWrapper);
13454e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
13464e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
13474e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
13484e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private int getFirstCheckedAction() {
13494e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        for (int i = 0, size = mActions.size(); i < size; i++) {
13504e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            if (mActions.get(i).isChecked()) {
13514e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu                return i;
13524e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            }
13534e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
13544e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        return 0;
13554e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
13564e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
13574e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    private void runImeAnimations(boolean entering) {
13584e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        ArrayList<Animator> animators = new ArrayList<Animator>();
13594e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        if (entering) {
13604e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            mGuidanceStylist.onImeAppearing(animators);
13614e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            mActionsStylist.onImeAppearing(animators);
1362d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            mButtonActionsStylist.onImeAppearing(animators);
13634e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        } else {
13644e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            mGuidanceStylist.onImeDisappearing(animators);
13654e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu            mActionsStylist.onImeDisappearing(animators);
1366d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu            mButtonActionsStylist.onImeDisappearing(animators);
13674e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        }
13684e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        AnimatorSet set = new AnimatorSet();
13694e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        set.playTogether(animators);
13704e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu        set.start();
13714e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu    }
13724e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu
13734e9bfff0d62ddb50391fecefdf8d98d59fb21387Dake Gu}
1374