GuidedActionsStylist.java revision 66e932ebd959ffe318f0780c5f689bac29b09b50
1ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/*
2ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Copyright (C) 2015 The Android Open Source Project
3ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing *
4ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * in compliance with the License. You may obtain a copy of the License at
6ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing *
7ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * http://www.apache.org/licenses/LICENSE-2.0
8ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing *
9ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Unless required by applicable law or agreed to in writing, software distributed under the License
10ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * or implied. See the License for the specific language governing permissions and limitations under
12ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * the License.
13ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */
14ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingpackage android.support.v17.leanback.widget;
15ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
168e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
173103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static android.support.v17.leanback.widget.GuidedAction.EDITING_ACTIVATOR_VIEW;
183103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static android.support.v17.leanback.widget.GuidedAction.EDITING_DESCRIPTION;
193103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static android.support.v17.leanback.widget.GuidedAction.EDITING_NONE;
203103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport static android.support.v17.leanback.widget.GuidedAction.EDITING_TITLE;
213103f63e99d47573823957f7aa34308555873221Aurimas Liutikas
22ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.animation.Animator;
23ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.animation.AnimatorInflater;
2466e932ebd959ffe318f0780c5f689bac29b09b50Dake Guimport android.animation.AnimatorListenerAdapter;
25ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.content.Context;
26ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.content.res.TypedArray;
27ae746be7c46297b910a99c07697e33e3a5fd7facDake Guimport android.graphics.Rect;
283103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.graphics.drawable.Drawable;
291ed9dc77616514e20c51baa67a04adab42e4135eDake Guimport android.os.Build.VERSION;
30ae746be7c46297b910a99c07697e33e3a5fd7facDake Guimport android.support.annotation.CallSuper;
31ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.annotation.NonNull;
32c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo;
33ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.R;
34ae746be7c46297b910a99c07697e33e3a5fd7facDake Guimport android.support.v17.leanback.transition.TransitionEpicenterCallback;
351ed9dc77616514e20c51baa67a04adab42e4135eDake Guimport android.support.v17.leanback.transition.TransitionHelper;
361ed9dc77616514e20c51baa67a04adab42e4135eDake Guimport android.support.v17.leanback.transition.TransitionListener;
37b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Guimport android.support.v17.leanback.widget.GuidedActionAdapter.EditListener;
38b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Guimport android.support.v17.leanback.widget.picker.DatePicker;
3911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Guimport android.support.v4.content.ContextCompat;
40ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v7.widget.RecyclerView;
41ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.text.TextUtils;
42ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.util.TypedValue;
431ed9dc77616514e20c51baa67a04adab42e4135eDake Guimport android.view.Gravity;
44ae746be7c46297b910a99c07697e33e3a5fd7facDake Guimport android.view.KeyEvent;
45ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.LayoutInflater;
46ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.View;
47b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Guimport android.view.View.AccessibilityDelegate;
48ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.ViewGroup;
49ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.WindowManager;
50b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Guimport android.view.accessibility.AccessibilityEvent;
51b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Guimport android.view.accessibility.AccessibilityNodeInfo;
5250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnataimport android.view.inputmethod.EditorInfo;
5311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Guimport android.widget.Checkable;
54ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesingimport android.widget.EditText;
55ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.ImageView;
56ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.TextView;
57ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
58b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Guimport java.util.Calendar;
59be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport java.util.Collections;
60ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport java.util.List;
61ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
62ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/**
63a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * GuidedActionsStylist is used within a {@link android.support.v17.leanback.app.GuidedStepFragment}
64a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * to supply the right-side panel where users can take actions. It consists of a container for the
65a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * list of actions, and a stationary selector view that indicates visually the location of focus.
66be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * GuidedActionsStylist has two different layouts: default is for normal actions including text,
67b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * radio, checkbox, DatePicker, etc, the other when {@link #setAsButtonActions()} is called is
68b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * recommended for button actions such as "yes", "no".
69ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
70ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Many aspects of the base GuidedActionsStylist can be customized through theming; see the
71ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * theme attributes below. Note that these attributes are not set on individual elements in layout
72ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * XML, but instead would be set in a custom theme. See
73ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <a href="http://developer.android.com/guide/topics/ui/themes.html">Styles and Themes</a>
74ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * for more information.
75ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
76ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * If these hooks are insufficient, this class may also be subclassed. Subclasses may wish to
77ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * override the {@link #onProvideLayoutId} method to change the layout used to display the
78b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * list container and selector; override {@link #onProvideItemLayoutId(int)} and
79b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * {@link #getItemViewType(GuidedAction)} method to change the layout used to display each action.
80b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <p>
81b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * To support a "click to activate" view similar to DatePicker, app needs:
82b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> Override {@link #onProvideItemLayoutId(int)} and {@link #getItemViewType(GuidedAction)},
83b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * provides a layout id for the action.
84b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> The layout must include a widget with id "guidedactions_activator_item", the widget is
85b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * toggled edit mode by {@link View#setActivated(boolean)}.
86b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> Override {@link #onBindActivatorView(ViewHolder, GuidedAction)} to populate values into View.
87b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> Override {@link #onUpdateActivatorView(ViewHolder, GuidedAction)} to update action.
88ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
89ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Note: If an alternate list layout is provided, the following view IDs must be supplied:
90ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <ul>
91ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_list}</li>
92ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * </ul><p>
93ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * These view IDs must be present in order for the stylist to function. The list ID must correspond
94ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * to a {@link VerticalGridView} or subclass.
95ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
96ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * If an alternate item layout is provided, the following view IDs should be used to refer to base
97ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * elements:
98ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <ul>
99ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_item_content}</li>
100ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_item_title}</li>
101ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_item_description}</li>
102ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_item_icon}</li>
103ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_item_checkmark}</li>
104ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <li>{@link android.support.v17.leanback.R.id#guidedactions_item_chevron}</li>
105ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * </ul><p>
106ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * These view IDs are allowed to be missing, in which case the corresponding views in {@link
107ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedActionsStylist.ViewHolder} will be null.
1084158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * <p>
1094158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * In order to support editable actions, the view associated with guidedactions_item_title should
1104158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * be a subclass of {@link android.widget.EditText}, and should satisfy the {@link
1114158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * ImeKeyMonitor} interface.
112ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing *
1134158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
1144158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
1151db5382081756ee276c1fb88f5ebdbc138b70249Dake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorDrawable
116ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsListStyle
117be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedSubActionsListStyle
118be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedButtonActionsListStyle
119ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemContainerStyle
120ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemCheckmarkStyle
121ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemIconStyle
122ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemContentStyle
123ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemTitleStyle
124ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemDescriptionStyle
125ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemChevronStyle
126ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionPressedAnimation
127ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionUnpressedAnimation
128ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionEnabledChevronAlpha
129ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDisabledChevronAlpha
130ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMinLines
131ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMaxLines
132ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDescriptionMinLines
133ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionVerticalPadding
13411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu * @see android.R.styleable#Theme_listChoiceIndicatorSingle
13511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu * @see android.R.styleable#Theme_listChoiceIndicatorMultiple
136ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see android.support.v17.leanback.app.GuidedStepFragment
137ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see GuidedAction
138ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */
139ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingpublic class GuidedActionsStylist implements FragmentAnimationProvider {
140ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
141ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
142e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Default viewType that associated with default layout Id for the action item.
143e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @see #getItemViewType(GuidedAction)
144e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @see #onProvideItemLayoutId(int)
145e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @see #onCreateViewHolder(ViewGroup, int)
146e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
147e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public static final int VIEW_TYPE_DEFAULT = 0;
148e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
149e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
150b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * ViewType for DatePicker.
151b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
152b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public static final int VIEW_TYPE_DATE_PICKER = 1;
153b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
15450c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    final static ItemAlignmentFacet sGuidedActionItemAlignFacet;
15550c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    static {
15650c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        sGuidedActionItemAlignFacet = new ItemAlignmentFacet();
15750c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        ItemAlignmentFacet.ItemAlignmentDef alignedDef = new ItemAlignmentFacet.ItemAlignmentDef();
15850c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentViewId(R.id.guidedactions_item_title);
15950c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setAlignedToTextViewBaseline(true);
16050c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentOffset(0);
16150c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentOffsetWithPadding(true);
16250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentOffsetPercent(0);
16350c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        sGuidedActionItemAlignFacet.setAlignmentDefs(new ItemAlignmentFacet.ItemAlignmentDef[]{alignedDef});
16450c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    }
16550c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata
166b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
167ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ViewHolder caches information about the action item layouts' subviews. Subclasses of {@link
168ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * GuidedActionsStylist} may also wish to subclass this in order to add fields.
169ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @see GuidedAction
170ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
17150c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    public static class ViewHolder extends RecyclerView.ViewHolder implements FacetProvider {
172ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
17399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        GuidedAction mAction;
174ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        private View mContentView;
17599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        TextView mTitleView;
17699ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        TextView mDescriptionView;
17799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        View mActivatorView;
17899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        ImageView mIconView;
17999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        ImageView mCheckmarkView;
18099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        ImageView mChevronView;
18199ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        int mEditingMode = EDITING_NONE;
182be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        private final boolean mIsSubAction;
18366e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        Animator mPressAnimator;
184ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
185b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu        final AccessibilityDelegate mDelegate = new AccessibilityDelegate() {
186b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            @Override
187b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
188b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                super.onInitializeAccessibilityEvent(host, event);
189b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                event.setChecked(mAction != null && mAction.isChecked());
190b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            }
191b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu
192b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            @Override
193b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
194b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                super.onInitializeAccessibilityNodeInfo(host, info);
195b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                info.setCheckable(
196b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                        mAction != null && mAction.getCheckSetId() != GuidedAction.NO_CHECK_SET);
197b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                info.setChecked(mAction != null && mAction.isChecked());
198b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            }
199b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu        };
200b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu
201ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
202ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Constructs an ViewHolder and caches the relevant subviews.
203ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
204ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ViewHolder(View v) {
205be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            this(v, false);
206be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
207be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
208be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
209be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * Constructs an ViewHolder for sub action and caches the relevant subviews.
210be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
211be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        public ViewHolder(View v, boolean isSubAction) {
212be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            super(v);
213ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
214ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mContentView = v.findViewById(R.id.guidedactions_item_content);
215ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mTitleView = (TextView) v.findViewById(R.id.guidedactions_item_title);
216b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            mActivatorView = v.findViewById(R.id.guidedactions_activator_item);
217ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mDescriptionView = (TextView) v.findViewById(R.id.guidedactions_item_description);
218ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mIconView = (ImageView) v.findViewById(R.id.guidedactions_item_icon);
219ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mCheckmarkView = (ImageView) v.findViewById(R.id.guidedactions_item_checkmark);
220ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mChevronView = (ImageView) v.findViewById(R.id.guidedactions_item_chevron);
221be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            mIsSubAction = isSubAction;
222b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu
223b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            v.setAccessibilityDelegate(mDelegate);
224ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
225ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
226ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
227ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the content view within this view holder's view, where title and description are
228ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * shown.
229ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
230ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public View getContentView() {
231ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mContentView;
232ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
233ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
234ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
235ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the title view within this view holder's view.
236ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
237ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public TextView getTitleView() {
238ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mTitleView;
239ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
240ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
241ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
242ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing         * Convenience method to return an editable version of the title, if possible,
243ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing         * or null if the title view isn't an EditText.
244ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing         */
245ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing        public EditText getEditableTitleView() {
246ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing            return (mTitleView instanceof EditText) ? (EditText)mTitleView : null;
247ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing        }
248ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing
249ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing        /**
250ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the description view within this view holder's view.
251ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
252ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public TextView getDescriptionView() {
253ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mDescriptionView;
254ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
255ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
256ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
257c1741246af607f6be2389056da0182c40f938348Dake Gu         * Convenience method to return an editable version of the description, if possible,
258c1741246af607f6be2389056da0182c40f938348Dake Gu         * or null if the description view isn't an EditText.
259c1741246af607f6be2389056da0182c40f938348Dake Gu         */
260c1741246af607f6be2389056da0182c40f938348Dake Gu        public EditText getEditableDescriptionView() {
261c1741246af607f6be2389056da0182c40f938348Dake Gu            return (mDescriptionView instanceof EditText) ? (EditText)mDescriptionView : null;
262c1741246af607f6be2389056da0182c40f938348Dake Gu        }
263c1741246af607f6be2389056da0182c40f938348Dake Gu
264c1741246af607f6be2389056da0182c40f938348Dake Gu        /**
265ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the icon view within this view holder's view.
266ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
267ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ImageView getIconView() {
268ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mIconView;
269ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
270ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
271ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
272ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the checkmark view within this view holder's view.
273ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
274ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ImageView getCheckmarkView() {
275ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mCheckmarkView;
276ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
277ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
278ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
279ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the chevron view within this view holder's view.
280ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
281ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ImageView getChevronView() {
282ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mChevronView;
283ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
284ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
285c1741246af607f6be2389056da0182c40f938348Dake Gu        /**
286b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if in editing title, description, or activator View, false otherwise.
287c1741246af607f6be2389056da0182c40f938348Dake Gu         */
288c1741246af607f6be2389056da0182c40f938348Dake Gu        public boolean isInEditing() {
289b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode != EDITING_NONE;
290b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
291b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
292b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        /**
293b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if in editing title, description, so IME would be open.
294b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * @return True if in editing title, description, so IME would be open, false otherwise.
295b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         */
296b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        public boolean isInEditingText() {
297b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_TITLE || mEditingMode == EDITING_DESCRIPTION;
298b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
299b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
300b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        /**
301b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if the TextView is in editing title, false otherwise.
302b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         */
303b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        public boolean isInEditingTitle() {
304b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_TITLE;
305c1741246af607f6be2389056da0182c40f938348Dake Gu        }
306c1741246af607f6be2389056da0182c40f938348Dake Gu
307c1741246af607f6be2389056da0182c40f938348Dake Gu        /**
308c1741246af607f6be2389056da0182c40f938348Dake Gu         * Returns true if the TextView is in editing description, false otherwise.
309c1741246af607f6be2389056da0182c40f938348Dake Gu         */
310c1741246af607f6be2389056da0182c40f938348Dake Gu        public boolean isInEditingDescription() {
311b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_DESCRIPTION;
312b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
313b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
314b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        /**
315b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if is in editing activator view with id guidedactions_activator_item, false
316b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * otherwise.
317b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         */
318b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        public boolean isInEditingActivatorView() {
319b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_ACTIVATOR_VIEW;
320c1741246af607f6be2389056da0182c40f938348Dake Gu        }
321c1741246af607f6be2389056da0182c40f938348Dake Gu
322be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
323b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * @return Current editing title view or description view or activator view or null if not
324b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * in editing.
325be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
326c1741246af607f6be2389056da0182c40f938348Dake Gu        public View getEditingView() {
327b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            switch(mEditingMode) {
328b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_TITLE:
329b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return mTitleView;
330b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_DESCRIPTION:
331b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return mDescriptionView;
332b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_ACTIVATOR_VIEW:
333b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return mActivatorView;
334b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_NONE:
335b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            default:
336c1741246af607f6be2389056da0182c40f938348Dake Gu                return null;
337c1741246af607f6be2389056da0182c40f938348Dake Gu            }
338c1741246af607f6be2389056da0182c40f938348Dake Gu        }
339be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
340be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
341be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * @return True if bound action is inside {@link GuidedAction#getSubActions()}, false
342be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * otherwise.
343be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
344be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        public boolean isSubAction() {
345be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            return mIsSubAction;
346be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
347be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
348be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
349be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * @return Currently bound action.
350be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
351be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        public GuidedAction getAction() {
352be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            return mAction;
353be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
3540f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu
3550f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu        void setActivated(boolean activated) {
3560f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            mActivatorView.setActivated(activated);
3570f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            if (itemView instanceof GuidedActionItemContainer) {
3580f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu                ((GuidedActionItemContainer) itemView).setFocusOutAllowed(!activated);
3590f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            }
3600f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu        }
36150c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata
36250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        @Override
36350c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        public Object getFacet(Class<?> facetClass) {
36450c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            if (facetClass == ItemAlignmentFacet.class) {
36550c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata                return sGuidedActionItemAlignFacet;
36650c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            }
36750c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            return null;
36850c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        }
36966e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu
37066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        void press(boolean pressed) {
37166e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            if (mPressAnimator != null) {
37266e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.cancel();
37366e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator = null;
37466e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            }
37566e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            final int themeAttrId = pressed ? R.attr.guidedActionPressedAnimation :
37666e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    R.attr.guidedActionUnpressedAnimation;
37766e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            Context ctx = itemView.getContext();
37866e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            TypedValue typedValue = new TypedValue();
37966e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            if (ctx.getTheme().resolveAttribute(themeAttrId, typedValue, true)) {
38066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator = AnimatorInflater.loadAnimator(ctx, typedValue.resourceId);
38166e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.setTarget(itemView);
38266e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.addListener(new AnimatorListenerAdapter() {
38366e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    @Override
38466e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    public void onAnimationEnd(Animator animation) {
38566e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                        mPressAnimator = null;
38666e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    }
38766e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                });
38866e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.start();
38966e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            }
39066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        }
391ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
392ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
393ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private static String TAG = "GuidedActionsStylist";
394ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
39599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    ViewGroup mMainView;
3960b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    private VerticalGridView mActionsGridView;
39799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    VerticalGridView mSubActionsGridView;
398fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu    private View mSubActionsBackground;
3990b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    private View mBgView;
4008e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu    private View mContentView;
4010b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    private boolean mButtonActions;
402ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
403ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    // Cached values from resources
404c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mEnabledTextAlpha;
405c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mDisabledTextAlpha;
406c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mEnabledDescriptionAlpha;
407c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mDisabledDescriptionAlpha;
408ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private float mEnabledChevronAlpha;
409ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private float mDisabledChevronAlpha;
410ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mTitleMinLines;
411ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mTitleMaxLines;
412ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mDescriptionMinLines;
413ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mVerticalPadding;
414ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mDisplayHeight;
415ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
416b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    private EditListener mEditListener;
417b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
418be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    private GuidedAction mExpandedAction = null;
41999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    Object mExpandTransition;
420ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    private boolean mBackToCollapseSubActions = true;
421ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    private boolean mBackToCollapseActivatorView = true;
422ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
423ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    private float mKeyLinePercent;
424be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
425ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
426ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Creates a view appropriate for displaying a list of GuidedActions, using the provided
427ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * inflater and container.
428ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <p>
429ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <i>Note: Does not actually add the created view to the container; the caller should do
430ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * this.</i>
431ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param inflater The layout inflater to be used when constructing the view.
432ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param container The view group to be passed in the call to
433ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <code>LayoutInflater.inflate</code>.
434ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The view to be added to the caller's view hierarchy.
435ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
43650c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    public View onCreateView(LayoutInflater inflater, final ViewGroup container) {
43750c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        TypedArray ta = inflater.getContext().getTheme().obtainStyledAttributes(
43850c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata                R.styleable.LeanbackGuidedStepTheme);
43950c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        float keylinePercent = ta.getFloat(R.styleable.LeanbackGuidedStepTheme_guidedStepKeyline,
44050c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata                40);
4418e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu        mMainView = (ViewGroup) inflater.inflate(onProvideLayoutId(), container, false);
442be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mContentView = mMainView.findViewById(mButtonActions ? R.id.guidedactions_content2 :
443be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                R.id.guidedactions_content);
444be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mBgView = mMainView.findViewById(mButtonActions ? R.id.guidedactions_list_background2 :
445be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                R.id.guidedactions_list_background);
446ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (mMainView instanceof VerticalGridView) {
447ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mActionsGridView = (VerticalGridView) mMainView;
448ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        } else {
4493103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            mActionsGridView = (VerticalGridView) mMainView.findViewById(mButtonActions
4503103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    ? R.id.guidedactions_list2 : R.id.guidedactions_list);
451ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (mActionsGridView == null) {
452ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                throw new IllegalStateException("No ListView exists.");
453ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
45450c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            mActionsGridView.setWindowAlignmentOffsetPercent(keylinePercent);
455ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mActionsGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
456be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            if (!mButtonActions) {
457be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                mSubActionsGridView = (VerticalGridView) mMainView.findViewById(
458be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                        R.id.guidedactions_sub_list);
459fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                mSubActionsBackground = mMainView.findViewById(
460fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                        R.id.guidedactions_sub_list_background);
461ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
462ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
463015eaf265571c84b5d37311f58bc69b2eb4af8d4Dake Gu        mActionsGridView.setFocusable(false);
464015eaf265571c84b5d37311f58bc69b2eb4af8d4Dake Gu        mActionsGridView.setFocusableInTouchMode(false);
465ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
466ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // Cache widths, chevron alpha values, max and min text lines, etc
467ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        Context ctx = mMainView.getContext();
468ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        TypedValue val = new TypedValue();
469ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mEnabledChevronAlpha = getFloat(ctx, val, R.attr.guidedActionEnabledChevronAlpha);
470ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mDisabledChevronAlpha = getFloat(ctx, val, R.attr.guidedActionDisabledChevronAlpha);
471ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mTitleMinLines = getInteger(ctx, val, R.attr.guidedActionTitleMinLines);
472ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mTitleMaxLines = getInteger(ctx, val, R.attr.guidedActionTitleMaxLines);
473ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mDescriptionMinLines = getInteger(ctx, val, R.attr.guidedActionDescriptionMinLines);
474ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mVerticalPadding = getDimension(ctx, val, R.attr.guidedActionVerticalPadding);
475ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mDisplayHeight = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
476ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                .getDefaultDisplay().getHeight();
477ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
478c1741246af607f6be2389056da0182c40f938348Dake Gu        mEnabledTextAlpha = Float.valueOf(ctx.getResources().getString(R.string
479c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_unselected_text_alpha));
480c1741246af607f6be2389056da0182c40f938348Dake Gu        mDisabledTextAlpha = Float.valueOf(ctx.getResources().getString(R.string
481c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_disabled_text_alpha));
482c1741246af607f6be2389056da0182c40f938348Dake Gu        mEnabledDescriptionAlpha = Float.valueOf(ctx.getResources().getString(R.string
483c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_unselected_description_text_alpha));
484c1741246af607f6be2389056da0182c40f938348Dake Gu        mDisabledDescriptionAlpha = Float.valueOf(ctx.getResources().getString(R.string
485c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_disabled_description_text_alpha));
486ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
487ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        mKeyLinePercent = GuidanceStylingRelativeLayout.getKeyLinePercent(ctx);
488ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (mContentView instanceof GuidedActionsRelativeLayout) {
489ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            ((GuidedActionsRelativeLayout) mContentView).setInterceptKeyEventListener(
490ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    new GuidedActionsRelativeLayout.InterceptKeyEventListener() {
491ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        @Override
492ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        public boolean onInterceptKeyEvent(KeyEvent event) {
493ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
494ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    && event.getAction() == KeyEvent.ACTION_UP
495ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    && mExpandedAction != null) {
496ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                if ((mExpandedAction.hasSubActions()
4973103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                                        && isBackKeyToCollapseSubActions())
4983103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                                        || (mExpandedAction.hasEditableActivatorView()
499ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                        && isBackKeyToCollapseActivatorView())) {
500ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    collapseAction(true);
501ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    return true;
502ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                }
503ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            }
504ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            return false;
505ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        }
506ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    }
507ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            );
508ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
509ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return mMainView;
510ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
511ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
5120b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    /**
513be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Choose the layout resource for button actions in {@link #onProvideLayoutId()}.
5140b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     */
5150b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    public void setAsButtonActions() {
516be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (mMainView != null) {
517be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            throw new IllegalStateException("setAsButtonActions() must be called before creating "
518be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    + "views");
5198e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu        }
520be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mButtonActions = true;
5210b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    }
5220b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu
5230b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    /**
524be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Returns true if it is button actions list, false for normal actions list.
525be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return True if it is button actions list, false for normal actions list.
5260b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     */
5270b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    public boolean isButtonActions() {
5280b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu        return mButtonActions;
5290b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    }
5300b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu
531d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
532d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Called when destroy the View created by GuidedActionsStylist.
533d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
534d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void onDestroyView() {
535be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mExpandedAction = null;
5361ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        mExpandTransition = null;
53743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mActionsGridView = null;
538be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mSubActionsGridView = null;
539fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu        mSubActionsBackground = null;
5408e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu        mContentView = null;
54143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mBgView = null;
54243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mMainView = null;
543d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
544d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
545ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
546ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Returns the VerticalGridView that displays the list of GuidedActions.
547ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The VerticalGridView for this presenter.
548ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
549ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public VerticalGridView getActionsGridView() {
550ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return mActionsGridView;
551ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
552ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
553ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
554be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Returns the VerticalGridView that displays the sub actions list of an expanded action.
555be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return The VerticalGridView that displays the sub actions list of an expanded action.
556be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
557be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public VerticalGridView getSubActionsGridView() {
558be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mSubActionsGridView;
559be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
560be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
561be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
562ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Provides the resource ID of the layout defining the host view for the list of guided actions.
563ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Subclasses may override to provide their own customized layouts. The base implementation
564be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * returns {@link android.support.v17.leanback.R.layout#lb_guidedactions} or
565be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * {@link android.support.v17.leanback.R.layout#lb_guidedbuttonactions} if
566be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * {@link #isButtonActions()} is true. If overridden, the substituted layout should contain
567be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * matching IDs for any views that should be managed by the base class; this can be achieved by
568be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * starting with a copy of the base layout file.
569be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     *
570be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return The resource ID of the layout to be inflated to define the host view for the list of
571be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     *         GuidedActions.
572ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
573ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public int onProvideLayoutId() {
574be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mButtonActions ? R.layout.lb_guidedbuttonactions : R.layout.lb_guidedactions;
575ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
576ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
577ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
578e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Return view type of action, each different type can have differently associated layout Id.
579e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Default implementation returns {@link #VIEW_TYPE_DEFAULT}.
580e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param action  The action object.
581e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @return View type that used in {@link #onProvideItemLayoutId(int)}.
582e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
583e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public int getItemViewType(GuidedAction action) {
584b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (action instanceof GuidedDatePickerAction) {
585b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return VIEW_TYPE_DATE_PICKER;
586b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
587e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        return VIEW_TYPE_DEFAULT;
588e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    }
589e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
590e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
591ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Provides the resource ID of the layout defining the view for an individual guided actions.
592ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Subclasses may override to provide their own customized layouts. The base implementation
593ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * returns {@link android.support.v17.leanback.R.layout#lb_guidedactions_item}. If overridden,
594ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * the substituted layout should contain matching IDs for any views that should be managed by
595ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing     * the base class; this can be achieved by starting with a copy of the base layout file. Note
596ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing     * that in order for the item to support editing, the title view should both subclass {@link
597ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing     * android.widget.EditText} and implement {@link ImeKeyMonitor}; see {@link
598e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * GuidedActionEditText}.  To support different types of Layouts, override {@link
599e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * #onProvideItemLayoutId(int)}.
600ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The resource ID of the layout to be inflated to define the view to display an
601ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * individual GuidedAction.
602ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
603ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public int onProvideItemLayoutId() {
604ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return R.layout.lb_guidedactions_item;
605ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
606ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
607ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
608e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Provides the resource ID of the layout defining the view for an individual guided actions.
609e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Subclasses may override to provide their own customized layouts. The base implementation
610b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * supports:
611b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * <li>{@link android.support.v17.leanback.R.layout#lb_guidedactions_item}
612b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * <li>{{@link android.support.v17.leanback.R.layout#lb_guidedactions_datepicker_item}. If
613b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * overridden, the substituted layout should contain matching IDs for any views that should be
614b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * managed by the base class; this can be achieved by starting with a copy of the base layout
615b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * file. Note that in order for the item to support editing, the title view should both subclass
616b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * {@link android.widget.EditText} and implement {@link ImeKeyMonitor}; see
617b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * {@link GuidedActionEditText}.
618b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     *
619e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param viewType View type returned by {@link #getItemViewType(GuidedAction)}
620e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @return The resource ID of the layout to be inflated to define the view to display an
621b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     *         individual GuidedAction.
622e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
623e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public int onProvideItemLayoutId(int viewType) {
624e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        if (viewType == VIEW_TYPE_DEFAULT) {
625e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu            return onProvideItemLayoutId();
626b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        } else if (viewType == VIEW_TYPE_DATE_PICKER) {
627b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return R.layout.lb_guidedactions_datepicker_item;
628e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        } else {
6293103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            throw new RuntimeException("ViewType " + viewType
6303103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    + " not supported in GuidedActionsStylist");
631e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        }
632e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    }
633e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
634e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
635ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Constructs a {@link ViewHolder} capable of representing {@link GuidedAction}s. Subclasses
636e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * may choose to return a subclass of ViewHolder.  To support different view types, override
637e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * {@link #onCreateViewHolder(ViewGroup, int)}
638ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <p>
639ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <i>Note: Should not actually add the created view to the parent; the caller will do
640ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * this.</i>
641ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param parent The view group to be used as the parent of the new view.
642ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The view to be added to the caller's view hierarchy.
643ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
644ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public ViewHolder onCreateViewHolder(ViewGroup parent) {
645ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
646ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        View v = inflater.inflate(onProvideItemLayoutId(), parent, false);
647be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return new ViewHolder(v, parent == mSubActionsGridView);
648ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
649ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
650ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
651e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Constructs a {@link ViewHolder} capable of representing {@link GuidedAction}s. Subclasses
652e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * may choose to return a subclass of ViewHolder.
653e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * <p>
654e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * <i>Note: Should not actually add the created view to the parent; the caller will do
655e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * this.</i>
656e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param parent The view group to be used as the parent of the new view.
657e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param viewType The viewType returned by {@link #getItemViewType(GuidedAction)}
658e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @return The view to be added to the caller's view hierarchy.
659e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
660e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
661e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        if (viewType == VIEW_TYPE_DEFAULT) {
662e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu            return onCreateViewHolder(parent);
663e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        }
664e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
665e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
666be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return new ViewHolder(v, parent == mSubActionsGridView);
667e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    }
668e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
669e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
670ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Binds a {@link ViewHolder} to a particular {@link GuidedAction}.
671ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder to be associated with the given action.
672ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param action The guided action to be displayed by the view holder's view.
673ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The view to be added to the caller's view hierarchy.
674ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
675ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onBindViewHolder(ViewHolder vh, GuidedAction action) {
676ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
677be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        vh.mAction = action;
678ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (vh.mTitleView != null) {
679ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            vh.mTitleView.setText(action.getTitle());
680c1741246af607f6be2389056da0182c40f938348Dake Gu            vh.mTitleView.setAlpha(action.isEnabled() ? mEnabledTextAlpha : mDisabledTextAlpha);
6816626b899cb2565105f20e4ee2060a5104826d1ddDake Gu            vh.mTitleView.setFocusable(false);
682ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mTitleView.setClickable(false);
683ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mTitleView.setLongClickable(false);
684ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
685ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (vh.mDescriptionView != null) {
686ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            vh.mDescriptionView.setText(action.getDescription());
6873103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            vh.mDescriptionView.setVisibility(TextUtils.isEmpty(action.getDescription())
6883103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    ? View.GONE : View.VISIBLE);
689c1741246af607f6be2389056da0182c40f938348Dake Gu            vh.mDescriptionView.setAlpha(action.isEnabled() ? mEnabledDescriptionAlpha :
690c1741246af607f6be2389056da0182c40f938348Dake Gu                mDisabledDescriptionAlpha);
6916626b899cb2565105f20e4ee2060a5104826d1ddDake Gu            vh.mDescriptionView.setFocusable(false);
692ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mDescriptionView.setClickable(false);
693ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mDescriptionView.setLongClickable(false);
694ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
695ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // Clients might want the check mark view to be gone entirely, in which case, ignore it.
69611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        if (vh.mCheckmarkView != null) {
69711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            onBindCheckMarkView(vh, action);
698ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
699023bf7d01378f30a63dce3d0a1112eb56bd6b99fDake Gu        setIcon(vh.mIconView, action);
700ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
701ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (action.hasMultilineDescription()) {
702ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (vh.mTitleView != null) {
703918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu                setMaxLines(vh.mTitleView, mTitleMaxLines);
704ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                if (vh.mDescriptionView != null) {
705be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    vh.mDescriptionView.setMaxHeight(getDescriptionMaxHeight(
706be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                            vh.itemView.getContext(), vh.mTitleView));
707ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                }
708ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
709ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        } else {
710ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (vh.mTitleView != null) {
711918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu                setMaxLines(vh.mTitleView, mTitleMinLines);
712ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
713ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (vh.mDescriptionView != null) {
714918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu                setMaxLines(vh.mDescriptionView, mDescriptionMinLines);
715ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
716ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
717b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (vh.mActivatorView != null) {
718b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            onBindActivatorView(vh, action);
719b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
720ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        setEditingMode(vh, false /*editing*/, false /*withTransition*/);
7217af424644dc8daae5298a5ca2f655770270366feDake Gu        if (action.isFocusable()) {
722be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.itemView.setFocusable(true);
723be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            ((ViewGroup) vh.itemView).setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
7247af424644dc8daae5298a5ca2f655770270366feDake Gu        } else {
725be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.itemView.setFocusable(false);
726be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            ((ViewGroup) vh.itemView).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
7277af424644dc8daae5298a5ca2f655770270366feDake Gu        }
7284705eed4421d3b00923b56062765206dea21387eDake Gu        setupImeOptions(vh, action);
729be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
730be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        updateChevronAndVisibility(vh);
7314705eed4421d3b00923b56062765206dea21387eDake Gu    }
7324705eed4421d3b00923b56062765206dea21387eDake Gu
733918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu    private static void setMaxLines(TextView view, int maxLines) {
734918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        // setSingleLine must be called before setMaxLines because it resets maximum to
735918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        // Integer.MAX_VALUE.
736918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        if (maxLines == 1) {
737918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu            view.setSingleLine(true);
738918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        } else {
739918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu            view.setSingleLine(false);
740918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu            view.setMaxLines(maxLines);
741918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        }
742918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu    }
743918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu
7444705eed4421d3b00923b56062765206dea21387eDake Gu    /**
7454705eed4421d3b00923b56062765206dea21387eDake Gu     * Called by {@link #onBindViewHolder(ViewHolder, GuidedAction)} to setup IME options.  Default
7464705eed4421d3b00923b56062765206dea21387eDake Gu     * implementation assigns {@link EditorInfo#IME_ACTION_DONE}.  Subclass may override.
7474705eed4421d3b00923b56062765206dea21387eDake Gu     * @param vh The view holder to be associated with the given action.
7484705eed4421d3b00923b56062765206dea21387eDake Gu     * @param action The guided action to be displayed by the view holder's view.
7494705eed4421d3b00923b56062765206dea21387eDake Gu     */
7504705eed4421d3b00923b56062765206dea21387eDake Gu    protected void setupImeOptions(ViewHolder vh, GuidedAction action) {
7514705eed4421d3b00923b56062765206dea21387eDake Gu        setupNextImeOptions(vh.getEditableTitleView());
7524705eed4421d3b00923b56062765206dea21387eDake Gu        setupNextImeOptions(vh.getEditableDescriptionView());
7534705eed4421d3b00923b56062765206dea21387eDake Gu    }
7544705eed4421d3b00923b56062765206dea21387eDake Gu
7554705eed4421d3b00923b56062765206dea21387eDake Gu    private void setupNextImeOptions(EditText edit) {
7564705eed4421d3b00923b56062765206dea21387eDake Gu        if (edit != null) {
7574705eed4421d3b00923b56062765206dea21387eDake Gu            edit.setImeOptions(EditorInfo.IME_ACTION_NEXT);
7584705eed4421d3b00923b56062765206dea21387eDake Gu        }
759c1741246af607f6be2389056da0182c40f938348Dake Gu    }
760c1741246af607f6be2389056da0182c40f938348Dake Gu
76177d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    /**
76277d397d533d04dfec663939692f2e048a072ee5bAlan Viverette     * @deprecated This method is for internal library use only and should not
76377d397d533d04dfec663939692f2e048a072ee5bAlan Viverette     *             be called directly.
76477d397d533d04dfec663939692f2e048a072ee5bAlan Viverette     */
76577d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    @Deprecated
76677d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    public void setEditingMode(ViewHolder vh, GuidedAction action, boolean editing) {
76777d397d533d04dfec663939692f2e048a072ee5bAlan Viverette        if (editing != vh.isInEditing() && isInExpandTransition()) {
76877d397d533d04dfec663939692f2e048a072ee5bAlan Viverette            onEditingModeChange(vh, action, editing);
76977d397d533d04dfec663939692f2e048a072ee5bAlan Viverette        }
77077d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    }
77177d397d533d04dfec663939692f2e048a072ee5bAlan Viverette
772ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void setEditingMode(ViewHolder vh, boolean editing) {
773ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        setEditingMode(vh, editing, true /*withTransition*/);
774ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
775ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
776ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void setEditingMode(ViewHolder vh, boolean editing, boolean withTransition) {
777b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (editing != vh.isInEditing() && !isInExpandTransition()) {
778ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            onEditingModeChange(vh, editing, withTransition);
779c1741246af607f6be2389056da0182c40f938348Dake Gu        }
780c1741246af607f6be2389056da0182c40f938348Dake Gu    }
781c1741246af607f6be2389056da0182c40f938348Dake Gu
782ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
783ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @deprecated Use {@link #onEditingModeChange(ViewHolder, boolean, boolean)}.
784ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
785ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @Deprecated
786c1741246af607f6be2389056da0182c40f938348Dake Gu    protected void onEditingModeChange(ViewHolder vh, GuidedAction action, boolean editing) {
787ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
788ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
789ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
790ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Called when editing mode of an ViewHolder is changed.  Subclass must call
791ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * <code>super.onEditingModeChange(vh,editing,withTransition)</code>.
792ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
793ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param vh                ViewHolder to change editing mode.
794ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param editing           True to enable editing, false to stop editing
795ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param withTransition    True to run expand transiiton, false otherwise.
796ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
797ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @CallSuper
798ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    protected void onEditingModeChange(ViewHolder vh, boolean editing, boolean withTransition) {
799ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        GuidedAction action = vh.getAction();
800c1741246af607f6be2389056da0182c40f938348Dake Gu        TextView titleView = vh.getTitleView();
801c1741246af607f6be2389056da0182c40f938348Dake Gu        TextView descriptionView = vh.getDescriptionView();
802c1741246af607f6be2389056da0182c40f938348Dake Gu        if (editing) {
803c1741246af607f6be2389056da0182c40f938348Dake Gu            CharSequence editTitle = action.getEditTitle();
804c1741246af607f6be2389056da0182c40f938348Dake Gu            if (titleView != null && editTitle != null) {
805c1741246af607f6be2389056da0182c40f938348Dake Gu                titleView.setText(editTitle);
806c1741246af607f6be2389056da0182c40f938348Dake Gu            }
807c1741246af607f6be2389056da0182c40f938348Dake Gu            CharSequence editDescription = action.getEditDescription();
808c1741246af607f6be2389056da0182c40f938348Dake Gu            if (descriptionView != null && editDescription != null) {
809c1741246af607f6be2389056da0182c40f938348Dake Gu                descriptionView.setText(editDescription);
810c1741246af607f6be2389056da0182c40f938348Dake Gu            }
811c1741246af607f6be2389056da0182c40f938348Dake Gu            if (action.isDescriptionEditable()) {
812c1741246af607f6be2389056da0182c40f938348Dake Gu                if (descriptionView != null) {
813c1741246af607f6be2389056da0182c40f938348Dake Gu                    descriptionView.setVisibility(View.VISIBLE);
8149562425bf9bc15281ac27df817141854769c1042Dake Gu                    descriptionView.setInputType(action.getDescriptionEditInputType());
815c1741246af607f6be2389056da0182c40f938348Dake Gu                }
816b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                vh.mEditingMode = EDITING_DESCRIPTION;
817b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (action.isEditable()){
8189562425bf9bc15281ac27df817141854769c1042Dake Gu                if (titleView != null) {
8199562425bf9bc15281ac27df817141854769c1042Dake Gu                    titleView.setInputType(action.getEditInputType());
8209562425bf9bc15281ac27df817141854769c1042Dake Gu                }
821b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                vh.mEditingMode = EDITING_TITLE;
822b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (vh.mActivatorView != null) {
823ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                onEditActivatorView(vh, editing, withTransition);
824b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                vh.mEditingMode = EDITING_ACTIVATOR_VIEW;
825c1741246af607f6be2389056da0182c40f938348Dake Gu            }
826c1741246af607f6be2389056da0182c40f938348Dake Gu        } else {
827c1741246af607f6be2389056da0182c40f938348Dake Gu            if (titleView != null) {
828c1741246af607f6be2389056da0182c40f938348Dake Gu                titleView.setText(action.getTitle());
829c1741246af607f6be2389056da0182c40f938348Dake Gu            }
830c1741246af607f6be2389056da0182c40f938348Dake Gu            if (descriptionView != null) {
831c1741246af607f6be2389056da0182c40f938348Dake Gu                descriptionView.setText(action.getDescription());
832c1741246af607f6be2389056da0182c40f938348Dake Gu            }
833b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            if (vh.mEditingMode == EDITING_DESCRIPTION) {
834c1741246af607f6be2389056da0182c40f938348Dake Gu                if (descriptionView != null) {
8353103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    descriptionView.setVisibility(TextUtils.isEmpty(action.getDescription())
8363103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                            ? View.GONE : View.VISIBLE);
8379562425bf9bc15281ac27df817141854769c1042Dake Gu                    descriptionView.setInputType(action.getDescriptionInputType());
838c1741246af607f6be2389056da0182c40f938348Dake Gu                }
839b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (vh.mEditingMode == EDITING_TITLE) {
8409562425bf9bc15281ac27df817141854769c1042Dake Gu                if (titleView != null) {
8419562425bf9bc15281ac27df817141854769c1042Dake Gu                    titleView.setInputType(action.getInputType());
8429562425bf9bc15281ac27df817141854769c1042Dake Gu                }
843b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (vh.mEditingMode == EDITING_ACTIVATOR_VIEW) {
844b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (vh.mActivatorView != null) {
845ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    onEditActivatorView(vh, editing, withTransition);
846b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
847c1741246af607f6be2389056da0182c40f938348Dake Gu            }
848b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mEditingMode = EDITING_NONE;
849c1741246af607f6be2389056da0182c40f938348Dake Gu        }
850ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        // call deprecated method for backward compatible
851ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        onEditingModeChange(vh, action, editing);
852ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
853ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
854ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
855ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Animates the view holder's view (or subviews thereof) when the action has had its focus
856ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * state changed.
857ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder associated with the relevant action.
858ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param focused True if the action has become focused, false if it has lost focus.
859ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
860ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onAnimateItemFocused(ViewHolder vh, boolean focused) {
861ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // No animations for this, currently, because the animation is done on
862ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // mSelectorView
863ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
864ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
865ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
866ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Animates the view holder's view (or subviews thereof) when the action has had its press
867ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * state changed.
868ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder associated with the relevant action.
869ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param pressed True if the action has been pressed, false if it has been unpressed.
870ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
871ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onAnimateItemPressed(ViewHolder vh, boolean pressed) {
87266e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        vh.press(pressed);
873ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
874ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
875ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
87619c1329def8d277c914cba46540d24bfde58b2a4Dake Gu     * Resets the view holder's view to unpressed state.
87719c1329def8d277c914cba46540d24bfde58b2a4Dake Gu     * @param vh The view holder associated with the relevant action.
87819c1329def8d277c914cba46540d24bfde58b2a4Dake Gu     */
87919c1329def8d277c914cba46540d24bfde58b2a4Dake Gu    public void onAnimateItemPressedCancelled(ViewHolder vh) {
88066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        vh.press(false);
88119c1329def8d277c914cba46540d24bfde58b2a4Dake Gu    }
88219c1329def8d277c914cba46540d24bfde58b2a4Dake Gu
88319c1329def8d277c914cba46540d24bfde58b2a4Dake Gu    /**
88411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Animates the view holder's view (or subviews thereof) when the action has had its check state
88511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * changed. Default implementation calls setChecked() if {@link ViewHolder#getCheckmarkView()}
88611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * is instance of {@link Checkable}.
88711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     *
888ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder associated with the relevant action.
889ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param checked True if the action has become checked, false if it has become unchecked.
89011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @see #onBindCheckMarkView(ViewHolder, GuidedAction)
891ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
892ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onAnimateItemChecked(ViewHolder vh, boolean checked) {
89311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        if (vh.mCheckmarkView instanceof Checkable) {
89411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            ((Checkable) vh.mCheckmarkView).setChecked(checked);
89511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        }
89611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    }
89711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu
89811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    /**
89911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Sets states of check mark view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}
90011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * when action's checkset Id is other than {@link GuidedAction#NO_CHECK_SET}. Default
90111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * implementation assigns drawable loaded from theme attribute
90211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * {@link android.R.attr#listChoiceIndicatorMultiple} for checkbox or
90311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * {@link android.R.attr#listChoiceIndicatorSingle} for radio button. Subclass rarely needs
90411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * override the method, instead app can provide its own drawable that supports transition
90511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * animations, change theme attributes {@link android.R.attr#listChoiceIndicatorMultiple} and
90611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * {@link android.R.attr#listChoiceIndicatorSingle} in {android.support.v17.leanback.R.
90711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * styleable#LeanbackGuidedStepTheme}.
90811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     *
90911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param vh The view holder associated with the relevant action.
91011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param action The GuidedAction object to bind to.
91111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @see #onAnimateItemChecked(ViewHolder, boolean)
91211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     */
91311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    public void onBindCheckMarkView(ViewHolder vh, GuidedAction action) {
91411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        if (action.getCheckSetId() != GuidedAction.NO_CHECK_SET) {
91511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            vh.mCheckmarkView.setVisibility(View.VISIBLE);
9163103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            int attrId = action.getCheckSetId() == GuidedAction.CHECKBOX_CHECK_SET_ID
9173103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    ? android.R.attr.listChoiceIndicatorMultiple
9183103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    : android.R.attr.listChoiceIndicatorSingle;
91911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            final Context context = vh.mCheckmarkView.getContext();
92011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            Drawable drawable = null;
92111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            TypedValue typedValue = new TypedValue();
92211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            if (context.getTheme().resolveAttribute(attrId, typedValue, true)) {
92311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu                drawable = ContextCompat.getDrawable(context, typedValue.resourceId);
924ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
92511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            vh.mCheckmarkView.setImageDrawable(drawable);
92611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            if (vh.mCheckmarkView instanceof Checkable) {
92711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu                ((Checkable) vh.mCheckmarkView).setChecked(action.isChecked());
92811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            }
92911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        } else {
93011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            vh.mCheckmarkView.setVisibility(View.GONE);
931ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
932ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
933ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
93411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    /**
935b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * Performs binding activator view value to action.  Default implementation supports
936b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * GuidedDatePickerAction, subclass may override to add support of other views.
937b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param vh ViewHolder of activator view.
938b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param action GuidedAction to bind.
939b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
940b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public void onBindActivatorView(ViewHolder vh, GuidedAction action) {
941b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (action instanceof GuidedDatePickerAction) {
942b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
943b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            DatePicker dateView = (DatePicker) vh.mActivatorView;
944b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            dateView.setDatePickerFormat(dateAction.getDatePickerFormat());
945942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            if (dateAction.getMinDate() != Long.MIN_VALUE) {
946942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu                dateView.setMinDate(dateAction.getMinDate());
947942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            }
948942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            if (dateAction.getMaxDate() != Long.MAX_VALUE) {
949942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu                dateView.setMaxDate(dateAction.getMaxDate());
950942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            }
951b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            Calendar c = Calendar.getInstance();
952942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            c.setTimeInMillis(dateAction.getDate());
953b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            dateView.updateDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
954b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    c.get(Calendar.DAY_OF_MONTH), false);
955b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
956b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
957b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
958b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
959b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * Performs updating GuidedAction from activator view.  Default implementation supports
960b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * GuidedDatePickerAction, subclass may override to add support of other views.
961b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param vh ViewHolder of activator view.
962b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param action GuidedAction to update.
963b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @return True if value has been updated, false otherwise.
964b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
965b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public boolean onUpdateActivatorView(ViewHolder vh, GuidedAction action) {
966b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (action instanceof GuidedDatePickerAction) {
967b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
968b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            DatePicker dateView = (DatePicker) vh.mActivatorView;
969b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            if (dateAction.getDate() != dateView.getDate()) {
970b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                dateAction.setDate(dateView.getDate());
971b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return true;
972b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            }
973b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
974b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        return false;
975b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
976b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
977b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
978b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * Sets listener for reporting view being edited.
979b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @hide
980b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
9818e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas    @RestrictTo(LIBRARY_GROUP)
982b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public void setEditListener(EditListener listener) {
983b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        mEditListener = listener;
984b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
985b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
986ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void onEditActivatorView(final ViewHolder vh, boolean editing, final boolean withTransition) {
987b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (editing) {
988b0818cc234e9df4312732f95fd6849922bfa0fa1Keyvan Amiri            startExpanded(vh, withTransition);
9890f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            vh.itemView.setFocusable(false);
990b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mActivatorView.requestFocus();
991b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mActivatorView.setOnClickListener(new View.OnClickListener() {
992b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                @Override
993b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                public void onClick(View v) {
994b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    if (!isInExpandTransition()) {
995ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        ((GuidedActionAdapter) getActionsGridView().getAdapter())
996ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                .performOnActionClick(vh);
997b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    }
998b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
999b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            });
1000b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        } else {
1001ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (onUpdateActivatorView(vh, vh.getAction())) {
1002b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (mEditListener != null) {
1003ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    mEditListener.onGuidedActionEditedAndProceed(vh.getAction());
1004b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1005b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            }
10060f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            vh.itemView.setFocusable(true);
1007b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.itemView.requestFocus();
1008ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            startExpanded(null, withTransition);
1009b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mActivatorView.setOnClickListener(null);
10100f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            vh.mActivatorView.setClickable(false);
1011b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
1012b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
1013b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
1014b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
101511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Sets states of chevron view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}.
101611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Subclass may override.
101711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     *
101811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param vh The view holder associated with the relevant action.
101911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param action The GuidedAction object to bind to.
102011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     */
102111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    public void onBindChevronView(ViewHolder vh, GuidedAction action) {
1022be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final boolean hasNext = action.hasNext();
1023be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final boolean hasSubActions = action.hasSubActions();
1024be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (hasNext || hasSubActions) {
1025be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.mChevronView.setVisibility(View.VISIBLE);
1026be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.mChevronView.setAlpha(action.isEnabled() ? mEnabledChevronAlpha :
1027be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    mDisabledChevronAlpha);
1028be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            if (hasNext) {
10297a45714d94e3e5566e3879042f7ee2b93eb5c62aDake Gu                float r = mMainView != null
10307a45714d94e3e5566e3879042f7ee2b93eb5c62aDake Gu                        && mMainView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? 180f : 0f;
10317a45714d94e3e5566e3879042f7ee2b93eb5c62aDake Gu                vh.mChevronView.setRotation(r);
1032be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            } else if (action == mExpandedAction) {
1033be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.mChevronView.setRotation(270);
1034be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            } else {
1035be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.mChevronView.setRotation(90);
1036be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
1037be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        } else {
1038be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.mChevronView.setVisibility(View.GONE);
1039be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1040be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1041be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1042be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1043be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
1044ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Expands or collapse the sub actions list view with transition animation
1045be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @param avh When not null, fill sub actions list of this ViewHolder into sub actions list and
1046be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * hide the other items in main list.  When null, collapse the sub actions list.
1047ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @deprecated use {@link #expandAction(GuidedAction, boolean)} and
1048ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * {@link #collapseAction(boolean)}
1049be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
1050ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @Deprecated
1051be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public void setExpandedViewHolder(ViewHolder avh) {
1052ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        expandAction(avh == null ? null : avh.getAction(), isExpandTransitionSupported());
10531ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    }
10541ed9dc77616514e20c51baa67a04adab42e4135eDake Gu
10551ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
10561ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Returns true if it is running an expanding or collapsing transition, false otherwise.
10571ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @return True if it is running an expanding or collapsing transition, false otherwise.
10581ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
10591ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public boolean isInExpandTransition() {
10601ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        return mExpandTransition != null;
10611ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    }
10621ed9dc77616514e20c51baa67a04adab42e4135eDake Gu
10631ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
10641ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Returns if expand/collapse animation is supported.  When this method returns true,
10651ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * {@link #startExpandedTransition(ViewHolder)} will be used.  When this method returns false,
10661ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * {@link #onUpdateExpandedViewHolder(ViewHolder)} will be called.
10671ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @return True if it is running an expanding or collapsing transition, false otherwise.
10681ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
10691ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public boolean isExpandTransitionSupported() {
10701ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        return VERSION.SDK_INT >= 21;
10711ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    }
10721ed9dc77616514e20c51baa67a04adab42e4135eDake Gu
10731ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
10741ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Start transition to expand or collapse GuidedActionStylist.
10751ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @param avh When not null, the GuidedActionStylist expands the sub actions of avh.  When null
10761ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * the GuidedActionStylist will collapse sub actions.
1077ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @deprecated use {@link #expandAction(GuidedAction, boolean)} and
1078ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * {@link #collapseAction(boolean)}
10791ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
1080ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @Deprecated
10811ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public void startExpandedTransition(ViewHolder avh) {
1082ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        expandAction(avh == null ? null : avh.getAction(), isExpandTransitionSupported());
1083ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1084ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1085ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1086ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Enable or disable using BACK key to collapse sub actions list. Default is enabled.
1087ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1088ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param backToCollapse True to enable using BACK key to collapse sub actions list, false
1089ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *                       to disable.
1090ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasSubActions
1091ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#getSubActions
1092ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1093ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final void setBackKeyToCollapseSubActions(boolean backToCollapse) {
1094ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        mBackToCollapseSubActions = backToCollapse;
1095ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1096ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1097ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1098ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @return True if using BACK key to collapse sub actions list, false otherwise. Default value
1099ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * is true.
1100ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1101ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasSubActions
1102ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#getSubActions
1103ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1104ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final boolean isBackKeyToCollapseSubActions() {
1105ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return mBackToCollapseSubActions;
1106ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1107ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1108ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1109ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Enable or disable using BACK key to collapse {@link GuidedAction} with editable activator
1110ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * view. Default is enabled.
1111ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1112ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param backToCollapse True to enable using BACK key to collapse {@link GuidedAction} with
1113ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *                       editable activator view.
1114ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasEditableActivatorView
1115ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1116ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final void setBackKeyToCollapseActivatorView(boolean backToCollapse) {
1117ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        mBackToCollapseActivatorView = backToCollapse;
1118ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1119ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1120ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1121ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @return True if using BACK key to collapse {@link GuidedAction} with editable activator
1122ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * view, false otherwise. Default value is true.
1123ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1124ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasEditableActivatorView
1125ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1126ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final boolean isBackKeyToCollapseActivatorView() {
1127ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return mBackToCollapseActivatorView;
1128ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1129ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1130ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1131ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Expand an action. Do nothing if it is in animation or there is action expanded.
1132ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1133ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param action         Action to expand.
1134ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param withTransition True to run transition animation, false otherwsie.
1135ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1136ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public void expandAction(GuidedAction action, final boolean withTransition) {
1137ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (isInExpandTransition() || mExpandedAction != null) {
1138ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1139ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1140ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        int actionPosition =
1141ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                ((GuidedActionAdapter) getActionsGridView().getAdapter()).indexOf(action);
1142ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (actionPosition < 0) {
1143ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1144ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1145ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        boolean runTransition = isExpandTransitionSupported() && withTransition;
1146ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (!runTransition) {
1147ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            getActionsGridView().setSelectedPosition(actionPosition,
1148ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    new ViewHolderTask() {
1149ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        @Override
1150ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        public void run(RecyclerView.ViewHolder vh) {
1151ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            GuidedActionsStylist.ViewHolder avh =
1152ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    (GuidedActionsStylist.ViewHolder)vh;
1153ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            if (avh.getAction().hasEditableActivatorView()) {
1154ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                setEditingMode(avh, true /*editing*/, false /*withTransition*/);
1155ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            } else {
1156ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                onUpdateExpandedViewHolder(avh);
1157ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            }
1158ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        }
1159ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    });
1160e5d263725fb60aa6a24f2221548afb20d0dc46e1Dake Gu            if (action.hasSubActions()) {
1161e5d263725fb60aa6a24f2221548afb20d0dc46e1Dake Gu                onUpdateSubActionsGridView(action, true);
1162e5d263725fb60aa6a24f2221548afb20d0dc46e1Dake Gu            }
1163ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        } else {
1164ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            getActionsGridView().setSelectedPosition(actionPosition,
1165ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    new ViewHolderTask() {
1166ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        @Override
1167ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        public void run(RecyclerView.ViewHolder vh) {
1168ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            GuidedActionsStylist.ViewHolder avh =
1169ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    (GuidedActionsStylist.ViewHolder)vh;
1170ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            if (avh.getAction().hasEditableActivatorView()) {
1171ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                setEditingMode(avh, true /*editing*/, true /*withTransition*/);
1172ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            } else {
1173ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                startExpanded(avh, true);
1174ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            }
1175ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        }
1176ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    });
1177ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1178ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1179ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1180ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1181ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1182ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Collapse expanded action. Do nothing if it is in animation or there is no action expanded.
1183ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1184ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param withTransition True to run transition animation, false otherwsie.
1185ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1186ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public void collapseAction(boolean withTransition) {
1187ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (isInExpandTransition() || mExpandedAction == null) {
1188ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1189ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1190ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        boolean runTransition = isExpandTransitionSupported() && withTransition;
1191ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        int actionPosition =
1192ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                ((GuidedActionAdapter) getActionsGridView().getAdapter()).indexOf(mExpandedAction);
1193ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (actionPosition < 0) {
1194ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1195ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1196ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (mExpandedAction.hasEditableActivatorView()) {
1197ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            setEditingMode(
1198ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    ((ViewHolder) getActionsGridView().findViewHolderForPosition(actionPosition)),
1199ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    false /*editing*/,
1200ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    runTransition);
1201ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        } else {
1202ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            startExpanded(null, runTransition);
1203ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1204ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1205ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1206ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    int getKeyLine() {
1207ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return (int) (mKeyLinePercent * mActionsGridView.getHeight() / 100);
1208ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1209ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1210ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1211ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Internal method with assumption we already scroll to the new ViewHolder or is currently
1212ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * expanded.
1213ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1214ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void startExpanded(ViewHolder avh, final boolean withTransition) {
12151ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        ViewHolder focusAvh = null; // expand / collapse view holder
12161ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        final int count = mActionsGridView.getChildCount();
12171ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        for (int i = 0; i < count; i++) {
12181ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            ViewHolder vh = (ViewHolder) mActionsGridView
12191ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                    .getChildViewHolder(mActionsGridView.getChildAt(i));
12201ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            if (avh == null && vh.itemView.getVisibility() == View.VISIBLE) {
12211ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                // going to collapse this one.
12221ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                focusAvh = vh;
12231ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                break;
12241ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            } else if (avh != null && vh.getAction() == avh.getAction()) {
12251ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                // going to expand this one.
12261ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                focusAvh = vh;
12271ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                break;
12281ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
12291ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
12301ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        if (focusAvh == null) {
12311ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            // huh?
12321ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            return;
12331ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
1234ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        boolean isExpand = avh != null;
1235b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        boolean isSubActionTransition = focusAvh.getAction().hasSubActions();
1236ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (withTransition) {
1237ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object set = TransitionHelper.createTransitionSet(false);
1238ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            float slideDistance = isSubActionTransition ? focusAvh.itemView.getHeight()
1239ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    : focusAvh.itemView.getHeight() * 0.5f;
1240ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object slideAndFade = TransitionHelper.createFadeAndShortSlide(
1241ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    Gravity.TOP | Gravity.BOTTOM,
1242ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    slideDistance);
1243ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.setEpicenterCallback(slideAndFade, new TransitionEpicenterCallback() {
1244ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                Rect mRect = new Rect();
1245ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                @Override
1246ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                public Rect onGetEpicenter(Object transition) {
1247ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    int centerY = getKeyLine();
1248ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    int centerX = 0;
1249ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    mRect.set(centerX, centerY, centerX, centerY);
1250ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    return mRect;
1251b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1252ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            });
1253ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object changeFocusItemTransform = TransitionHelper.createChangeTransform();
1254ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object changeFocusItemBounds = TransitionHelper.createChangeBounds(false);
12553103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN
12563103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    | TransitionHelper.FADE_OUT);
1257ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object changeGridBounds = TransitionHelper.createChangeBounds(false);
1258ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (avh == null) {
1259ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(slideAndFade, 150);
1260ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemTransform, 100);
1261ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemBounds, 100);
1262ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeGridBounds, 100);
12631ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            } else {
1264ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(fade, 100);
1265ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeGridBounds, 50);
1266ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemTransform, 50);
1267ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemBounds, 50);
12681ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
1269ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            for (int i = 0; i < count; i++) {
1270ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                ViewHolder vh = (ViewHolder) mActionsGridView
1271ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        .getChildViewHolder(mActionsGridView.getChildAt(i));
1272ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                if (vh == focusAvh) {
1273ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    // going to expand/collapse this one.
1274ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    if (isSubActionTransition) {
1275ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        TransitionHelper.include(changeFocusItemTransform, vh.itemView);
1276ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        TransitionHelper.include(changeFocusItemBounds, vh.itemView);
1277ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    }
1278ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                } else {
1279ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    // going to slide this item to top / bottom.
1280ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    TransitionHelper.include(slideAndFade, vh.itemView);
1281ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    TransitionHelper.exclude(fade, vh.itemView, true);
1282ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                }
1283ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            }
1284ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.include(changeGridBounds, mSubActionsGridView);
1285ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.include(changeGridBounds, mSubActionsBackground);
1286ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransition(set, slideAndFade);
1287ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            // note that we don't run ChangeBounds for activating view due to the rounding problem
1288ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            // of multiple level views ChangeBounds animation causing vertical jittering.
1289ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (isSubActionTransition) {
1290ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.addTransition(set, changeFocusItemTransform);
1291ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.addTransition(set, changeFocusItemBounds);
12921ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
1293ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransition(set, fade);
1294ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransition(set, changeGridBounds);
1295ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            mExpandTransition = set;
1296ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransitionListener(mExpandTransition, new TransitionListener() {
12971ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                @Override
1298ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                public void onTransitionEnd(Object transition) {
1299ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    mExpandTransition = null;
13001ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                }
13011ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            });
1302ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (isExpand && isSubActionTransition) {
1303ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // To expand sub actions, move original position of sub actions to bottom of item
1304ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                int startY = avh.itemView.getBottom();
1305ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                mSubActionsGridView.offsetTopAndBottom(startY - mSubActionsGridView.getTop());
1306ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                mSubActionsBackground.offsetTopAndBottom(startY - mSubActionsBackground.getTop());
1307ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            }
1308ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.beginDelayedTransition(mMainView, mExpandTransition);
13091ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
13101ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        onUpdateExpandedViewHolder(avh);
1311ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (isSubActionTransition) {
1312ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            onUpdateSubActionsGridView(focusAvh.getAction(), isExpand);
1313ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1314be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1315be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1316be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
1317be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return True if sub actions list is expanded.
1318be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
1319be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public boolean isSubActionsExpanded() {
1320ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return mExpandedAction != null && mExpandedAction.hasSubActions();
1321ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1322ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1323ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1324ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @return True if there is {@link #getExpandedAction()} is not null, false otherwise.
1325ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1326ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public boolean isExpanded() {
1327be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mExpandedAction != null;
1328be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1329be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1330be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
1331be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return Current expanded GuidedAction or null if not expanded.
1332be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
1333be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public GuidedAction getExpandedAction() {
1334be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mExpandedAction;
1335be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1336be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
13371ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
13381ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Expand or collapse GuidedActionStylist.
13391ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @param avh When not null, the GuidedActionStylist expands the sub actions of avh.  When null
13401ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * the GuidedActionStylist will collapse sub actions.
13411ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
13421ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public void onUpdateExpandedViewHolder(ViewHolder avh) {
1343b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri
1344b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // Note about setting the prune child flag back & forth here: without this, the actions that
1345b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // go off the screen from the top or bottom become invisible forever. This is because once
1346b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // an action is expanded, it takes more space which in turn kicks out some other actions
1347b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // off of the screen. Once, this action is collapsed (after the second click) and the
1348b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // visibility flag is set back to true for all existing actions,
1349b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // the off-the-screen actions are pruned from the view, thus
1350b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // could not be accessed, had we not disabled pruning prior to this.
13511ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        if (avh == null) {
13521ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            mExpandedAction = null;
1353b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri            mActionsGridView.setPruneChild(true);
13541ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        } else if (avh.getAction() != mExpandedAction) {
13551ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            mExpandedAction = avh.getAction();
1356b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri            mActionsGridView.setPruneChild(false);
13571ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
1358fb23f1271e21761bb523948d9ea9c60c42ae7251Dake Gu        // In expanding mode, notifyItemChange on expanded item will reset the translationY by
1359fb23f1271e21761bb523948d9ea9c60c42ae7251Dake Gu        // the default ItemAnimator.  So disable ItemAnimation in expanding mode.
1360fb23f1271e21761bb523948d9ea9c60c42ae7251Dake Gu        mActionsGridView.setAnimateChildLayout(false);
1361be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final int count = mActionsGridView.getChildCount();
1362be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        for (int i = 0; i < count; i++) {
1363be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            ViewHolder vh = (ViewHolder) mActionsGridView
1364be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    .getChildViewHolder(mActionsGridView.getChildAt(i));
1365be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            updateChevronAndVisibility(vh);
1366be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1367ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1368ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1369ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void onUpdateSubActionsGridView(GuidedAction action, boolean expand) {
1370be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (mSubActionsGridView != null) {
1371ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            ViewGroup.MarginLayoutParams lp =
1372ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    (ViewGroup.MarginLayoutParams) mSubActionsGridView.getLayoutParams();
1373ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            GuidedActionAdapter adapter = (GuidedActionAdapter) mSubActionsGridView.getAdapter();
1374ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (expand) {
1375ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // set to negative value so GuidedActionRelativeLayout will override with
1376ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // keyLine percentage.
1377ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                lp.topMargin = -2;
13781ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                lp.height = ViewGroup.MarginLayoutParams.MATCH_PARENT;
13791ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setLayoutParams(lp);
13801ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setVisibility(View.VISIBLE);
1381fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                mSubActionsBackground.setVisibility(View.VISIBLE);
13821ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.requestFocus();
1383ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                adapter.setActions(action.getSubActions());
1384ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            } else {
1385ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // set to explicit value, which will disable the keyLine percentage calculation
1386ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // in GuidedRelativeLayout.
1387ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                int actionPosition = ((GuidedActionAdapter) mActionsGridView.getAdapter())
1388ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        .indexOf(action);
1389ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                lp.topMargin = mActionsGridView.getLayoutManager()
1390ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        .findViewByPosition(actionPosition).getBottom();
1391ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                lp.height = 0;
13921ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setVisibility(View.INVISIBLE);
1393fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                mSubActionsBackground.setVisibility(View.INVISIBLE);
13941ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setLayoutParams(lp);
1395ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                adapter.setActions(Collections.EMPTY_LIST);
13961ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mActionsGridView.requestFocus();
13971ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
1398be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1399be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1400be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1401be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    private void updateChevronAndVisibility(ViewHolder vh) {
1402be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (!vh.isSubAction()) {
14031ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            if (mExpandedAction == null) {
14041ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                vh.itemView.setVisibility(View.VISIBLE);
14051ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                vh.itemView.setTranslationY(0);
1406b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (vh.mActivatorView != null) {
14070f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu                    vh.setActivated(false);
1408b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
14091ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            } else if (vh.getAction() == mExpandedAction) {
1410be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.itemView.setVisibility(View.VISIBLE);
1411b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (vh.getAction().hasSubActions()) {
1412ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    vh.itemView.setTranslationY(getKeyLine() - vh.itemView.getBottom());
1413b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                } else if (vh.mActivatorView != null) {
1414b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    vh.itemView.setTranslationY(0);
14150f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu                    vh.setActivated(true);
1416b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1417be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            } else {
1418be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.itemView.setVisibility(View.INVISIBLE);
14191ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                vh.itemView.setTranslationY(0);
1420be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
1421be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1422be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (vh.mChevronView != null) {
1423be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            onBindChevronView(vh, vh.getAction());
1424be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
142511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    }
142611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu
1427ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /*
1428ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1429ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * FragmentAnimationProvider overrides
1430ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1431ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1432ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1433ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
1434ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * {@inheritDoc}
1435ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1436ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    @Override
14374158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    public void onImeAppearing(@NonNull List<Animator> animators) {
14384158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    }
14394158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing
14404158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    /**
14414158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing     * {@inheritDoc}
14424158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing     */
14434158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    @Override
14444158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    public void onImeDisappearing(@NonNull List<Animator> animators) {
14454158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    }
14464158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing
1447ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /*
1448ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1449ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Private methods
1450ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1451ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1452ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1453ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private float getFloat(Context ctx, TypedValue typedValue, int attrId) {
1454ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        ctx.getTheme().resolveAttribute(attrId, typedValue, true);
1455ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // Android resources don't have a native float type, so we have to use strings.
1456ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return Float.valueOf(ctx.getResources().getString(typedValue.resourceId));
1457ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1458ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1459ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int getInteger(Context ctx, TypedValue typedValue, int attrId) {
1460ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        ctx.getTheme().resolveAttribute(attrId, typedValue, true);
1461ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return ctx.getResources().getInteger(typedValue.resourceId);
1462ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1463ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1464ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int getDimension(Context ctx, TypedValue typedValue, int attrId) {
1465ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        ctx.getTheme().resolveAttribute(attrId, typedValue, true);
1466ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return ctx.getResources().getDimensionPixelSize(typedValue.resourceId);
1467ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1468ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1469ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private boolean setIcon(final ImageView iconView, GuidedAction action) {
1470ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        Drawable icon = null;
1471ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (iconView != null) {
1472ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            icon = action.getIcon();
1473ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (icon != null) {
1474162b21598d9f4fd49748b3c7e27501fe1277210dChristopher Lane                // setImageDrawable resets the drawable's level unless we set the view level first.
1475162b21598d9f4fd49748b3c7e27501fe1277210dChristopher Lane                iconView.setImageLevel(icon.getLevel());
1476ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                iconView.setImageDrawable(icon);
1477ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                iconView.setVisibility(View.VISIBLE);
1478ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            } else {
1479ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                iconView.setVisibility(View.GONE);
1480ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
1481ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
1482ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return icon != null;
1483ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1484ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1485ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
1486ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return the max height in pixels the description can be such that the
1487ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     *         action nicely takes up the entire screen.
1488ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1489ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int getDescriptionMaxHeight(Context context, TextView title) {
1490ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // The 2 multiplier on the title height calculation is a
1491ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // conservative estimate for font padding which can not be
1492ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // calculated at this stage since the view hasn't been rendered yet.
1493ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return (int)(mDisplayHeight - 2*mVerticalPadding - 2*mTitleMaxLines*title.getLineHeight());
1494ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1495ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1496ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing}
1497