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 */
14ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.widget;
15ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.widget.GuidedAction.EDITING_ACTIVATOR_VIEW;
18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.widget.GuidedAction.EDITING_DESCRIPTION;
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.widget.GuidedAction.EDITING_NONE;
20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.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;
30306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.text.InputType;
31ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.text.TextUtils;
32ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.util.TypedValue;
331ed9dc77616514e20c51baa67a04adab42e4135eDake Guimport android.view.Gravity;
34ae746be7c46297b910a99c07697e33e3a5fd7facDake Guimport android.view.KeyEvent;
35ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.LayoutInflater;
36ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.View;
37b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Guimport android.view.View.AccessibilityDelegate;
38ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.ViewGroup;
39ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.WindowManager;
40b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Guimport android.view.accessibility.AccessibilityEvent;
41b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Guimport android.view.accessibility.AccessibilityNodeInfo;
4250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnataimport android.view.inputmethod.EditorInfo;
4311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Guimport android.widget.Checkable;
44ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesingimport android.widget.EditText;
45ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.ImageView;
46ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.TextView;
47ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
488619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.CallSuper;
498619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.NonNull;
508619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.RestrictTo;
518619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.core.content.ContextCompat;
52d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Guimport androidx.core.os.BuildCompat;
538619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.R;
548619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.transition.TransitionEpicenterCallback;
558619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.transition.TransitionHelper;
568619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.transition.TransitionListener;
578619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.widget.GuidedActionAdapter.EditListener;
588619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.widget.picker.DatePicker;
598619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.recyclerview.widget.RecyclerView;
608619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas
61b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Guimport java.util.Calendar;
62be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Guimport java.util.Collections;
63ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport java.util.List;
64ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
65ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/**
66ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * GuidedActionsStylist is used within a {@link androidx.leanback.app.GuidedStepFragment}
67a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * to supply the right-side panel where users can take actions. It consists of a container for the
68a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * list of actions, and a stationary selector view that indicates visually the location of focus.
69be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * GuidedActionsStylist has two different layouts: default is for normal actions including text,
70b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * radio, checkbox, DatePicker, etc, the other when {@link #setAsButtonActions()} is called is
71b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * recommended for button actions such as "yes", "no".
72ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
73ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Many aspects of the base GuidedActionsStylist can be customized through theming; see the
74ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * theme attributes below. Note that these attributes are not set on individual elements in layout
75ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * XML, but instead would be set in a custom theme. See
76ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <a href="http://developer.android.com/guide/topics/ui/themes.html">Styles and Themes</a>
77ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * for more information.
78ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
79ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * If these hooks are insufficient, this class may also be subclassed. Subclasses may wish to
80ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * override the {@link #onProvideLayoutId} method to change the layout used to display the
81b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * list container and selector; override {@link #onProvideItemLayoutId(int)} and
82b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * {@link #getItemViewType(GuidedAction)} method to change the layout used to display each action.
83b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <p>
84b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * To support a "click to activate" view similar to DatePicker, app needs:
85b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> Override {@link #onProvideItemLayoutId(int)} and {@link #getItemViewType(GuidedAction)},
86b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * provides a layout id for the action.
87b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> The layout must include a widget with id "guidedactions_activator_item", the widget is
88b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * toggled edit mode by {@link View#setActivated(boolean)}.
89b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> Override {@link #onBindActivatorView(ViewHolder, GuidedAction)} to populate values into View.
90b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu * <li> Override {@link #onUpdateActivatorView(ViewHolder, GuidedAction)} to update action.
91ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
92ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Note: If an alternate list layout is provided, the following view IDs must be supplied:
93ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <ul>
94ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_list}</li>
95ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * </ul><p>
96ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * These view IDs must be present in order for the stylist to function. The list ID must correspond
97ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * to a {@link VerticalGridView} or subclass.
98ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <p>
99ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * If an alternate item layout is provided, the following view IDs should be used to refer to base
100ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * elements:
101ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * <ul>
102ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_item_content}</li>
103ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_item_title}</li>
104ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_item_description}</li>
105ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_item_icon}</li>
106ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_item_checkmark}</li>
107ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * <li>{@link androidx.leanback.R.id#guidedactions_item_chevron}</li>
108ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * </ul><p>
109ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * These view IDs are allowed to be missing, in which case the corresponding views in {@link
110ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedActionsStylist.ViewHolder} will be null.
1114158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * <p>
1124158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * In order to support editable actions, the view associated with guidedactions_item_title should
1134158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * be a subclass of {@link android.widget.EditText}, and should satisfy the {@link
114d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu * ImeKeyMonitor} interface and {@link GuidedActionAutofillSupport} interface.
115ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing *
116ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
117ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
118ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorDrawable
119ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsListStyle
120ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedSubActionsListStyle
121ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedButtonActionsListStyle
122ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemContainerStyle
123ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemCheckmarkStyle
124ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemIconStyle
125ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemContentStyle
126ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemTitleStyle
127ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemDescriptionStyle
128ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemChevronStyle
129ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionPressedAnimation
130ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionUnpressedAnimation
131ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionEnabledChevronAlpha
132ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDisabledChevronAlpha
133ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMinLines
134ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMaxLines
135ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDescriptionMinLines
136ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @attr ref androidx.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionVerticalPadding
13711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu * @see android.R.styleable#Theme_listChoiceIndicatorSingle
13811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu * @see android.R.styleable#Theme_listChoiceIndicatorMultiple
139ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * @see androidx.leanback.app.GuidedStepFragment
140ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @see GuidedAction
141ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */
142ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingpublic class GuidedActionsStylist implements FragmentAnimationProvider {
143ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
144ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
145e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Default viewType that associated with default layout Id for the action item.
146e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @see #getItemViewType(GuidedAction)
147e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @see #onProvideItemLayoutId(int)
148e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @see #onCreateViewHolder(ViewGroup, int)
149e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
150e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public static final int VIEW_TYPE_DEFAULT = 0;
151e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
152e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
153b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * ViewType for DatePicker.
154b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
155b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public static final int VIEW_TYPE_DATE_PICKER = 1;
156b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
15750c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    final static ItemAlignmentFacet sGuidedActionItemAlignFacet;
158df715f15ab54e487840c51f9fedd9a4409856096susnata
15950c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    static {
16050c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        sGuidedActionItemAlignFacet = new ItemAlignmentFacet();
16150c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        ItemAlignmentFacet.ItemAlignmentDef alignedDef = new ItemAlignmentFacet.ItemAlignmentDef();
16250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentViewId(R.id.guidedactions_item_title);
16350c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setAlignedToTextViewBaseline(true);
16450c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentOffset(0);
16550c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentOffsetWithPadding(true);
16650c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        alignedDef.setItemAlignmentOffsetPercent(0);
16750c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        sGuidedActionItemAlignFacet.setAlignmentDefs(new ItemAlignmentFacet.ItemAlignmentDef[]{alignedDef});
16850c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    }
16950c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata
170b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
171ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ViewHolder caches information about the action item layouts' subviews. Subclasses of {@link
172ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * GuidedActionsStylist} may also wish to subclass this in order to add fields.
173ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @see GuidedAction
174ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
17550c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    public static class ViewHolder extends RecyclerView.ViewHolder implements FacetProvider {
176ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
17799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        GuidedAction mAction;
178ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        private View mContentView;
17999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        TextView mTitleView;
18099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        TextView mDescriptionView;
18199ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        View mActivatorView;
18299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        ImageView mIconView;
18399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        ImageView mCheckmarkView;
18499ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        ImageView mChevronView;
18599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas        int mEditingMode = EDITING_NONE;
186be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        private final boolean mIsSubAction;
18766e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        Animator mPressAnimator;
188ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
189b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu        final AccessibilityDelegate mDelegate = new AccessibilityDelegate() {
190b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            @Override
191b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
192b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                super.onInitializeAccessibilityEvent(host, event);
193b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                event.setChecked(mAction != null && mAction.isChecked());
194b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            }
195b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu
196b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            @Override
197b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
198b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                super.onInitializeAccessibilityNodeInfo(host, info);
199b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                info.setCheckable(
200b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                        mAction != null && mAction.getCheckSetId() != GuidedAction.NO_CHECK_SET);
201b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu                info.setChecked(mAction != null && mAction.isChecked());
202b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            }
203b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu        };
204b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu
205ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
206ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Constructs an ViewHolder and caches the relevant subviews.
207ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
208ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ViewHolder(View v) {
209be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            this(v, false);
210be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
211be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
212be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
213be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * Constructs an ViewHolder for sub action and caches the relevant subviews.
214be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
215be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        public ViewHolder(View v, boolean isSubAction) {
216be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            super(v);
217ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
218ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mContentView = v.findViewById(R.id.guidedactions_item_content);
219ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mTitleView = (TextView) v.findViewById(R.id.guidedactions_item_title);
220b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            mActivatorView = v.findViewById(R.id.guidedactions_activator_item);
221ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mDescriptionView = (TextView) v.findViewById(R.id.guidedactions_item_description);
222ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mIconView = (ImageView) v.findViewById(R.id.guidedactions_item_icon);
223ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mCheckmarkView = (ImageView) v.findViewById(R.id.guidedactions_item_checkmark);
224ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mChevronView = (ImageView) v.findViewById(R.id.guidedactions_item_chevron);
225be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            mIsSubAction = isSubAction;
226b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu
227b6b910bb30da6b2af318e77d0ab2f3575187f7bcDake Gu            v.setAccessibilityDelegate(mDelegate);
228ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
229ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
230ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
231ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the content view within this view holder's view, where title and description are
232ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * shown.
233ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
234ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public View getContentView() {
235ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mContentView;
236ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
237ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
238ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
239ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the title view within this view holder's view.
240ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
241ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public TextView getTitleView() {
242ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mTitleView;
243ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
244ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
245ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
246ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing         * Convenience method to return an editable version of the title, if possible,
247ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing         * or null if the title view isn't an EditText.
248ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing         */
249ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing        public EditText getEditableTitleView() {
250ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing            return (mTitleView instanceof EditText) ? (EditText)mTitleView : null;
251ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing        }
252ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing
253ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing        /**
254ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the description view within this view holder's view.
255ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
256ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public TextView getDescriptionView() {
257ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mDescriptionView;
258ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
259ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
260ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
261c1741246af607f6be2389056da0182c40f938348Dake Gu         * Convenience method to return an editable version of the description, if possible,
262c1741246af607f6be2389056da0182c40f938348Dake Gu         * or null if the description view isn't an EditText.
263c1741246af607f6be2389056da0182c40f938348Dake Gu         */
264c1741246af607f6be2389056da0182c40f938348Dake Gu        public EditText getEditableDescriptionView() {
265c1741246af607f6be2389056da0182c40f938348Dake Gu            return (mDescriptionView instanceof EditText) ? (EditText)mDescriptionView : null;
266c1741246af607f6be2389056da0182c40f938348Dake Gu        }
267c1741246af607f6be2389056da0182c40f938348Dake Gu
268c1741246af607f6be2389056da0182c40f938348Dake Gu        /**
269ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the icon view within this view holder's view.
270ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
271ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ImageView getIconView() {
272ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mIconView;
273ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
274ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
275ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
276ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the checkmark view within this view holder's view.
277ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
278ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ImageView getCheckmarkView() {
279ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mCheckmarkView;
280ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
281ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
282ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        /**
283ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         * Returns the chevron view within this view holder's view.
284ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing         */
285ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        public ImageView getChevronView() {
286ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            return mChevronView;
287ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
288ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
289c1741246af607f6be2389056da0182c40f938348Dake Gu        /**
290b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if in editing title, description, or activator View, false otherwise.
291c1741246af607f6be2389056da0182c40f938348Dake Gu         */
292c1741246af607f6be2389056da0182c40f938348Dake Gu        public boolean isInEditing() {
293b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode != EDITING_NONE;
294b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
295b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
296b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        /**
297b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if in editing title, description, so IME would be open.
298b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * @return True if in editing title, description, so IME would be open, false otherwise.
299b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         */
300b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        public boolean isInEditingText() {
301b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_TITLE || mEditingMode == EDITING_DESCRIPTION;
302b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
303b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
304b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        /**
305b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if the TextView is in editing title, false otherwise.
306b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         */
307b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        public boolean isInEditingTitle() {
308b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_TITLE;
309c1741246af607f6be2389056da0182c40f938348Dake Gu        }
310c1741246af607f6be2389056da0182c40f938348Dake Gu
311c1741246af607f6be2389056da0182c40f938348Dake Gu        /**
312c1741246af607f6be2389056da0182c40f938348Dake Gu         * Returns true if the TextView is in editing description, false otherwise.
313c1741246af607f6be2389056da0182c40f938348Dake Gu         */
314c1741246af607f6be2389056da0182c40f938348Dake Gu        public boolean isInEditingDescription() {
315b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_DESCRIPTION;
316b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
317b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
318b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        /**
319b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * Returns true if is in editing activator view with id guidedactions_activator_item, false
320b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * otherwise.
321b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         */
322b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        public boolean isInEditingActivatorView() {
323b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return mEditingMode == EDITING_ACTIVATOR_VIEW;
324c1741246af607f6be2389056da0182c40f938348Dake Gu        }
325c1741246af607f6be2389056da0182c40f938348Dake Gu
326be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
327b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * @return Current editing title view or description view or activator view or null if not
328b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu         * in editing.
329be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
330c1741246af607f6be2389056da0182c40f938348Dake Gu        public View getEditingView() {
331b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            switch(mEditingMode) {
332b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_TITLE:
333b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return mTitleView;
334b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_DESCRIPTION:
335b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return mDescriptionView;
336b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_ACTIVATOR_VIEW:
337b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return mActivatorView;
338b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            case EDITING_NONE:
339b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            default:
340c1741246af607f6be2389056da0182c40f938348Dake Gu                return null;
341c1741246af607f6be2389056da0182c40f938348Dake Gu            }
342c1741246af607f6be2389056da0182c40f938348Dake Gu        }
343be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
344be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
345be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * @return True if bound action is inside {@link GuidedAction#getSubActions()}, false
346be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * otherwise.
347be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
348be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        public boolean isSubAction() {
349be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            return mIsSubAction;
350be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
351be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
352be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        /**
353be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         * @return Currently bound action.
354be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu         */
355be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        public GuidedAction getAction() {
356be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            return mAction;
357be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
3580f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu
3590f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu        void setActivated(boolean activated) {
3600f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            mActivatorView.setActivated(activated);
3610f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            if (itemView instanceof GuidedActionItemContainer) {
3620f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu                ((GuidedActionItemContainer) itemView).setFocusOutAllowed(!activated);
3630f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            }
3640f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu        }
36550c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata
36650c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        @Override
36750c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        public Object getFacet(Class<?> facetClass) {
36850c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            if (facetClass == ItemAlignmentFacet.class) {
36950c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata                return sGuidedActionItemAlignFacet;
37050c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            }
37150c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            return null;
37250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        }
37366e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu
37466e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        void press(boolean pressed) {
37566e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            if (mPressAnimator != null) {
37666e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.cancel();
37766e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator = null;
37866e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            }
37966e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            final int themeAttrId = pressed ? R.attr.guidedActionPressedAnimation :
38066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    R.attr.guidedActionUnpressedAnimation;
38166e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            Context ctx = itemView.getContext();
38266e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            TypedValue typedValue = new TypedValue();
38366e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            if (ctx.getTheme().resolveAttribute(themeAttrId, typedValue, true)) {
38466e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator = AnimatorInflater.loadAnimator(ctx, typedValue.resourceId);
38566e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.setTarget(itemView);
38666e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.addListener(new AnimatorListenerAdapter() {
38766e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    @Override
38866e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    public void onAnimationEnd(Animator animation) {
38966e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                        mPressAnimator = null;
39066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                    }
39166e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                });
39266e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu                mPressAnimator.start();
39366e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu            }
39466e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        }
395ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
396ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
397f8a82a95a1a962ec05536f7196fcee0f1384a497Jake Wharton    private static final String TAG = "GuidedActionsStylist";
398ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
39999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    ViewGroup mMainView;
4000b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    private VerticalGridView mActionsGridView;
40199ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    VerticalGridView mSubActionsGridView;
402fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu    private View mSubActionsBackground;
4030b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    private View mBgView;
4048e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu    private View mContentView;
4050b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    private boolean mButtonActions;
406ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
407ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    // Cached values from resources
408c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mEnabledTextAlpha;
409c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mDisabledTextAlpha;
410c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mEnabledDescriptionAlpha;
411c1741246af607f6be2389056da0182c40f938348Dake Gu    private float mDisabledDescriptionAlpha;
412ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private float mEnabledChevronAlpha;
413ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private float mDisabledChevronAlpha;
414ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mTitleMinLines;
415ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mTitleMaxLines;
416ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mDescriptionMinLines;
417ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mVerticalPadding;
418ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int mDisplayHeight;
419ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
420b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    private EditListener mEditListener;
421b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
422be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    private GuidedAction mExpandedAction = null;
42399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    Object mExpandTransition;
424ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    private boolean mBackToCollapseSubActions = true;
425ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    private boolean mBackToCollapseActivatorView = true;
426ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
427ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    private float mKeyLinePercent;
428be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
429ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
430ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Creates a view appropriate for displaying a list of GuidedActions, using the provided
431ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * inflater and container.
432ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <p>
433ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <i>Note: Does not actually add the created view to the container; the caller should do
434ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * this.</i>
435ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param inflater The layout inflater to be used when constructing the view.
436ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param container The view group to be passed in the call to
437ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <code>LayoutInflater.inflate</code>.
438ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The view to be added to the caller's view hierarchy.
439ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
44050c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata    public View onCreateView(LayoutInflater inflater, final ViewGroup container) {
44150c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        TypedArray ta = inflater.getContext().getTheme().obtainStyledAttributes(
44250c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata                R.styleable.LeanbackGuidedStepTheme);
44350c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata        float keylinePercent = ta.getFloat(R.styleable.LeanbackGuidedStepTheme_guidedStepKeyline,
44450c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata                40);
4458e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu        mMainView = (ViewGroup) inflater.inflate(onProvideLayoutId(), container, false);
446be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mContentView = mMainView.findViewById(mButtonActions ? R.id.guidedactions_content2 :
447be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                R.id.guidedactions_content);
448be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mBgView = mMainView.findViewById(mButtonActions ? R.id.guidedactions_list_background2 :
449be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                R.id.guidedactions_list_background);
450ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (mMainView instanceof VerticalGridView) {
451ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mActionsGridView = (VerticalGridView) mMainView;
452ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        } else {
4533103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            mActionsGridView = (VerticalGridView) mMainView.findViewById(mButtonActions
4543103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    ? R.id.guidedactions_list2 : R.id.guidedactions_list);
455ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (mActionsGridView == null) {
456ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                throw new IllegalStateException("No ListView exists.");
457ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
45850c611b216a4b2c8eb2bbd2a2848bb6da34677besusnata            mActionsGridView.setWindowAlignmentOffsetPercent(keylinePercent);
459ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            mActionsGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
460be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            if (!mButtonActions) {
461be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                mSubActionsGridView = (VerticalGridView) mMainView.findViewById(
462be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                        R.id.guidedactions_sub_list);
463fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                mSubActionsBackground = mMainView.findViewById(
464fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                        R.id.guidedactions_sub_list_background);
465ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
466ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
467015eaf265571c84b5d37311f58bc69b2eb4af8d4Dake Gu        mActionsGridView.setFocusable(false);
468015eaf265571c84b5d37311f58bc69b2eb4af8d4Dake Gu        mActionsGridView.setFocusableInTouchMode(false);
469ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
470ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // Cache widths, chevron alpha values, max and min text lines, etc
471ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        Context ctx = mMainView.getContext();
472ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        TypedValue val = new TypedValue();
473ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mEnabledChevronAlpha = getFloat(ctx, val, R.attr.guidedActionEnabledChevronAlpha);
474ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mDisabledChevronAlpha = getFloat(ctx, val, R.attr.guidedActionDisabledChevronAlpha);
475ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mTitleMinLines = getInteger(ctx, val, R.attr.guidedActionTitleMinLines);
476ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mTitleMaxLines = getInteger(ctx, val, R.attr.guidedActionTitleMaxLines);
477ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mDescriptionMinLines = getInteger(ctx, val, R.attr.guidedActionDescriptionMinLines);
478ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mVerticalPadding = getDimension(ctx, val, R.attr.guidedActionVerticalPadding);
479ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        mDisplayHeight = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
480ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                .getDefaultDisplay().getHeight();
481ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
482c1741246af607f6be2389056da0182c40f938348Dake Gu        mEnabledTextAlpha = Float.valueOf(ctx.getResources().getString(R.string
483c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_unselected_text_alpha));
484c1741246af607f6be2389056da0182c40f938348Dake Gu        mDisabledTextAlpha = Float.valueOf(ctx.getResources().getString(R.string
485c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_disabled_text_alpha));
486c1741246af607f6be2389056da0182c40f938348Dake Gu        mEnabledDescriptionAlpha = Float.valueOf(ctx.getResources().getString(R.string
487c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_unselected_description_text_alpha));
488c1741246af607f6be2389056da0182c40f938348Dake Gu        mDisabledDescriptionAlpha = Float.valueOf(ctx.getResources().getString(R.string
489c1741246af607f6be2389056da0182c40f938348Dake Gu                .lb_guidedactions_item_disabled_description_text_alpha));
490ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
491ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        mKeyLinePercent = GuidanceStylingRelativeLayout.getKeyLinePercent(ctx);
492ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (mContentView instanceof GuidedActionsRelativeLayout) {
493ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            ((GuidedActionsRelativeLayout) mContentView).setInterceptKeyEventListener(
494ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    new GuidedActionsRelativeLayout.InterceptKeyEventListener() {
495ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        @Override
496ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        public boolean onInterceptKeyEvent(KeyEvent event) {
497ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
498ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    && event.getAction() == KeyEvent.ACTION_UP
499ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    && mExpandedAction != null) {
500ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                if ((mExpandedAction.hasSubActions()
5013103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                                        && isBackKeyToCollapseSubActions())
5023103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                                        || (mExpandedAction.hasEditableActivatorView()
503ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                        && isBackKeyToCollapseActivatorView())) {
504ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    collapseAction(true);
505ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    return true;
506ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                }
507ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            }
508ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            return false;
509ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        }
510ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    }
511ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            );
512ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
513ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return mMainView;
514ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
515ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
5160b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    /**
517be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Choose the layout resource for button actions in {@link #onProvideLayoutId()}.
5180b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     */
5190b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    public void setAsButtonActions() {
520be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (mMainView != null) {
521be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            throw new IllegalStateException("setAsButtonActions() must be called before creating "
522be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    + "views");
5238e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu        }
524be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mButtonActions = true;
5250b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    }
5260b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu
5270b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    /**
528be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Returns true if it is button actions list, false for normal actions list.
529be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return True if it is button actions list, false for normal actions list.
5300b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu     */
5310b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    public boolean isButtonActions() {
5320b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu        return mButtonActions;
5330b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu    }
5340b3811639349fd5791a3f330b23b7e4b1c099c27Dake Gu
535d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    /**
536d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     * Called when destroy the View created by GuidedActionsStylist.
537d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu     */
538d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    public void onDestroyView() {
539be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mExpandedAction = null;
5401ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        mExpandTransition = null;
54143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mActionsGridView = null;
542be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        mSubActionsGridView = null;
543fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu        mSubActionsBackground = null;
5448e5ae27d6db125867640b672cc97d4a158fdfd48Dake Gu        mContentView = null;
54543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mBgView = null;
54643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu        mMainView = null;
547d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu    }
548d14724d33d61385c27a00c31bbc67ad8eeb57b3cDake Gu
549ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
550ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Returns the VerticalGridView that displays the list of GuidedActions.
551ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The VerticalGridView for this presenter.
552ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
553ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public VerticalGridView getActionsGridView() {
554ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return mActionsGridView;
555ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
556ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
557ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
558be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * Returns the VerticalGridView that displays the sub actions list of an expanded action.
559be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return The VerticalGridView that displays the sub actions list of an expanded action.
560be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
561be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public VerticalGridView getSubActionsGridView() {
562be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mSubActionsGridView;
563be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
564be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
565be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
566ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Provides the resource ID of the layout defining the host view for the list of guided actions.
567ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Subclasses may override to provide their own customized layouts. The base implementation
568ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * returns {@link androidx.leanback.R.layout#lb_guidedactions} or
569ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.leanback.R.layout#lb_guidedbuttonactions} if
570be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * {@link #isButtonActions()} is true. If overridden, the substituted layout should contain
571be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * matching IDs for any views that should be managed by the base class; this can be achieved by
572be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * starting with a copy of the base layout file.
573be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     *
574be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return The resource ID of the layout to be inflated to define the host view for the list of
575be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     *         GuidedActions.
576ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
577ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public int onProvideLayoutId() {
578be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mButtonActions ? R.layout.lb_guidedbuttonactions : R.layout.lb_guidedactions;
579ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
580ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
581ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
582e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Return view type of action, each different type can have differently associated layout Id.
583e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Default implementation returns {@link #VIEW_TYPE_DEFAULT}.
584e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param action  The action object.
585e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @return View type that used in {@link #onProvideItemLayoutId(int)}.
586e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
587e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public int getItemViewType(GuidedAction action) {
588b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (action instanceof GuidedDatePickerAction) {
589b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return VIEW_TYPE_DATE_PICKER;
590b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
591e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        return VIEW_TYPE_DEFAULT;
592e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    }
593e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
594e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
595ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Provides the resource ID of the layout defining the view for an individual guided actions.
596ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Subclasses may override to provide their own customized layouts. The base implementation
597ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * returns {@link androidx.leanback.R.layout#lb_guidedactions_item}. If overridden,
598ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * the substituted layout should contain matching IDs for any views that should be managed by
599ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing     * the base class; this can be achieved by starting with a copy of the base layout file. Note
600ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing     * that in order for the item to support editing, the title view should both subclass {@link
601d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu     * android.widget.EditText} and implement {@link ImeKeyMonitor},
602d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu     * {@link GuidedActionAutofillSupport}; see {@link
603e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * GuidedActionEditText}.  To support different types of Layouts, override {@link
604e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * #onProvideItemLayoutId(int)}.
605ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The resource ID of the layout to be inflated to define the view to display an
606ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * individual GuidedAction.
607ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
608ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public int onProvideItemLayoutId() {
609ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return R.layout.lb_guidedactions_item;
610ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
611ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
612ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
613e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Provides the resource ID of the layout defining the view for an individual guided actions.
614e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Subclasses may override to provide their own customized layouts. The base implementation
615b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * supports:
616ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * <li>{@link androidx.leanback.R.layout#lb_guidedactions_item}
617ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * <li>{{@link androidx.leanback.R.layout#lb_guidedactions_datepicker_item}. If
618b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * overridden, the substituted layout should contain matching IDs for any views that should be
619b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * managed by the base class; this can be achieved by starting with a copy of the base layout
620b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * file. Note that in order for the item to support editing, the title view should both subclass
621b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * {@link android.widget.EditText} and implement {@link ImeKeyMonitor}; see
622b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * {@link GuidedActionEditText}.
623b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     *
624e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param viewType View type returned by {@link #getItemViewType(GuidedAction)}
625e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @return The resource ID of the layout to be inflated to define the view to display an
626b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     *         individual GuidedAction.
627e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
628e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public int onProvideItemLayoutId(int viewType) {
629e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        if (viewType == VIEW_TYPE_DEFAULT) {
630e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu            return onProvideItemLayoutId();
631b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        } else if (viewType == VIEW_TYPE_DATE_PICKER) {
632b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            return R.layout.lb_guidedactions_datepicker_item;
633e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        } else {
6343103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            throw new RuntimeException("ViewType " + viewType
6353103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    + " not supported in GuidedActionsStylist");
636e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        }
637e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    }
638e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
639e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
640ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Constructs a {@link ViewHolder} capable of representing {@link GuidedAction}s. Subclasses
641e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * may choose to return a subclass of ViewHolder.  To support different view types, override
642e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * {@link #onCreateViewHolder(ViewGroup, int)}
643ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <p>
644ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * <i>Note: Should not actually add the created view to the parent; the caller will do
645ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * this.</i>
646ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param parent The view group to be used as the parent of the new view.
647ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The view to be added to the caller's view hierarchy.
648ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
649ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public ViewHolder onCreateViewHolder(ViewGroup parent) {
650ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
651ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        View v = inflater.inflate(onProvideItemLayoutId(), parent, false);
652be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return new ViewHolder(v, parent == mSubActionsGridView);
653ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
654ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
655ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
656e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * Constructs a {@link ViewHolder} capable of representing {@link GuidedAction}s. Subclasses
657e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * may choose to return a subclass of ViewHolder.
658e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * <p>
659e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * <i>Note: Should not actually add the created view to the parent; the caller will do
660e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * this.</i>
661e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param parent The view group to be used as the parent of the new view.
662e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @param viewType The viewType returned by {@link #getItemViewType(GuidedAction)}
663e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     * @return The view to be added to the caller's view hierarchy.
664e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu     */
665e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
666e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        if (viewType == VIEW_TYPE_DEFAULT) {
667e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu            return onCreateViewHolder(parent);
668e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        }
669e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
670e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu        View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
671be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return new ViewHolder(v, parent == mSubActionsGridView);
672e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    }
673e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu
674e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu    /**
675ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Binds a {@link ViewHolder} to a particular {@link GuidedAction}.
676ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder to be associated with the given action.
677ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param action The guided action to be displayed by the view holder's view.
678ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return The view to be added to the caller's view hierarchy.
679ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
680ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onBindViewHolder(ViewHolder vh, GuidedAction action) {
681be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        vh.mAction = action;
682ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (vh.mTitleView != null) {
683ce678995ede4a5e09486145727fe76f231a7c866Dake Gu            vh.mTitleView.setInputType(action.getInputType());
684ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            vh.mTitleView.setText(action.getTitle());
685c1741246af607f6be2389056da0182c40f938348Dake Gu            vh.mTitleView.setAlpha(action.isEnabled() ? mEnabledTextAlpha : mDisabledTextAlpha);
6866626b899cb2565105f20e4ee2060a5104826d1ddDake Gu            vh.mTitleView.setFocusable(false);
687ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mTitleView.setClickable(false);
688ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mTitleView.setLongClickable(false);
689d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu            if (BuildCompat.isAtLeastP()) {
690d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                if (action.isEditable()) {
691d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                    vh.mTitleView.setAutofillHints(action.getAutofillHints());
692d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                } else {
693d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                    vh.mTitleView.setAutofillHints((String[]) null);
694d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                }
695d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu            } else if (VERSION.SDK_INT >= 26) {
696d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                // disable autofill below P as dpad/keyboard is not supported
697d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                vh.mTitleView.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
698d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu            }
699ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
700ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (vh.mDescriptionView != null) {
701ce678995ede4a5e09486145727fe76f231a7c866Dake Gu            vh.mDescriptionView.setInputType(action.getDescriptionInputType());
702ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            vh.mDescriptionView.setText(action.getDescription());
7033103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            vh.mDescriptionView.setVisibility(TextUtils.isEmpty(action.getDescription())
7043103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    ? View.GONE : View.VISIBLE);
705c1741246af607f6be2389056da0182c40f938348Dake Gu            vh.mDescriptionView.setAlpha(action.isEnabled() ? mEnabledDescriptionAlpha :
706c1741246af607f6be2389056da0182c40f938348Dake Gu                mDisabledDescriptionAlpha);
7076626b899cb2565105f20e4ee2060a5104826d1ddDake Gu            vh.mDescriptionView.setFocusable(false);
708ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mDescriptionView.setClickable(false);
709ed6ddac644df9949403f1a01e1224a37cb568febDake Gu            vh.mDescriptionView.setLongClickable(false);
710d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu            if (BuildCompat.isAtLeastP()) {
711d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                if (action.isDescriptionEditable()) {
712d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                    vh.mDescriptionView.setAutofillHints(action.getAutofillHints());
713d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                } else {
714d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                    vh.mDescriptionView.setAutofillHints((String[]) null);
715d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                }
716d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu            } else if (VERSION.SDK_INT >= 26) {
717d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                // disable autofill below P as dpad/keyboard is not supported
718d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu                vh.mTitleView.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
719d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu            }
720ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
721ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // Clients might want the check mark view to be gone entirely, in which case, ignore it.
72211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        if (vh.mCheckmarkView != null) {
72311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            onBindCheckMarkView(vh, action);
724ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
725023bf7d01378f30a63dce3d0a1112eb56bd6b99fDake Gu        setIcon(vh.mIconView, action);
726ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
727ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (action.hasMultilineDescription()) {
728ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (vh.mTitleView != null) {
729918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu                setMaxLines(vh.mTitleView, mTitleMaxLines);
730306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli                vh.mTitleView.setInputType(
731306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli                        vh.mTitleView.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
732ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                if (vh.mDescriptionView != null) {
733306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli                    vh.mDescriptionView.setInputType(vh.mDescriptionView.getInputType()
734306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli                            | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
735be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    vh.mDescriptionView.setMaxHeight(getDescriptionMaxHeight(
736be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                            vh.itemView.getContext(), vh.mTitleView));
737ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                }
738ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
739ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        } else {
740ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (vh.mTitleView != null) {
741918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu                setMaxLines(vh.mTitleView, mTitleMinLines);
742ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
743ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (vh.mDescriptionView != null) {
744918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu                setMaxLines(vh.mDescriptionView, mDescriptionMinLines);
745ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
746ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
747b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (vh.mActivatorView != null) {
748b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            onBindActivatorView(vh, action);
749b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
750ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        setEditingMode(vh, false /*editing*/, false /*withTransition*/);
7517af424644dc8daae5298a5ca2f655770270366feDake Gu        if (action.isFocusable()) {
752be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.itemView.setFocusable(true);
753be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            ((ViewGroup) vh.itemView).setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
7547af424644dc8daae5298a5ca2f655770270366feDake Gu        } else {
755be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.itemView.setFocusable(false);
756be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            ((ViewGroup) vh.itemView).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
7577af424644dc8daae5298a5ca2f655770270366feDake Gu        }
7584705eed4421d3b00923b56062765206dea21387eDake Gu        setupImeOptions(vh, action);
759be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
760be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        updateChevronAndVisibility(vh);
7614705eed4421d3b00923b56062765206dea21387eDake Gu    }
7624705eed4421d3b00923b56062765206dea21387eDake Gu
763df715f15ab54e487840c51f9fedd9a4409856096susnata    /**
764df715f15ab54e487840c51f9fedd9a4409856096susnata     * Switches action to edit mode and pops up the keyboard.
765df715f15ab54e487840c51f9fedd9a4409856096susnata     */
766df715f15ab54e487840c51f9fedd9a4409856096susnata    public void openInEditMode(GuidedAction action) {
767df715f15ab54e487840c51f9fedd9a4409856096susnata        final GuidedActionAdapter guidedActionAdapter =
768df715f15ab54e487840c51f9fedd9a4409856096susnata                (GuidedActionAdapter) getActionsGridView().getAdapter();
769df715f15ab54e487840c51f9fedd9a4409856096susnata        int actionIndex = guidedActionAdapter.getActions().indexOf(action);
770df715f15ab54e487840c51f9fedd9a4409856096susnata        if (actionIndex < 0 || !action.isEditable()) {
771df715f15ab54e487840c51f9fedd9a4409856096susnata            return;
772df715f15ab54e487840c51f9fedd9a4409856096susnata        }
773df715f15ab54e487840c51f9fedd9a4409856096susnata
774df715f15ab54e487840c51f9fedd9a4409856096susnata        getActionsGridView().setSelectedPosition(actionIndex, new ViewHolderTask() {
775df715f15ab54e487840c51f9fedd9a4409856096susnata            @Override
776df715f15ab54e487840c51f9fedd9a4409856096susnata            public void run(RecyclerView.ViewHolder viewHolder) {
777df715f15ab54e487840c51f9fedd9a4409856096susnata                ViewHolder vh = (ViewHolder) viewHolder;
778df715f15ab54e487840c51f9fedd9a4409856096susnata                guidedActionAdapter.mGroup.openIme(guidedActionAdapter, vh);
779df715f15ab54e487840c51f9fedd9a4409856096susnata            }
780df715f15ab54e487840c51f9fedd9a4409856096susnata        });
781df715f15ab54e487840c51f9fedd9a4409856096susnata    }
782df715f15ab54e487840c51f9fedd9a4409856096susnata
783918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu    private static void setMaxLines(TextView view, int maxLines) {
784918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        // setSingleLine must be called before setMaxLines because it resets maximum to
785918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        // Integer.MAX_VALUE.
786918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        if (maxLines == 1) {
787918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu            view.setSingleLine(true);
788918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        } else {
789918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu            view.setSingleLine(false);
790918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu            view.setMaxLines(maxLines);
791918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu        }
792918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu    }
793918306ceb829009d348a749a7a648ba3a727e2c3Dake Gu
7944705eed4421d3b00923b56062765206dea21387eDake Gu    /**
7954705eed4421d3b00923b56062765206dea21387eDake Gu     * Called by {@link #onBindViewHolder(ViewHolder, GuidedAction)} to setup IME options.  Default
7964705eed4421d3b00923b56062765206dea21387eDake Gu     * implementation assigns {@link EditorInfo#IME_ACTION_DONE}.  Subclass may override.
7974705eed4421d3b00923b56062765206dea21387eDake Gu     * @param vh The view holder to be associated with the given action.
7984705eed4421d3b00923b56062765206dea21387eDake Gu     * @param action The guided action to be displayed by the view holder's view.
7994705eed4421d3b00923b56062765206dea21387eDake Gu     */
8004705eed4421d3b00923b56062765206dea21387eDake Gu    protected void setupImeOptions(ViewHolder vh, GuidedAction action) {
8014705eed4421d3b00923b56062765206dea21387eDake Gu        setupNextImeOptions(vh.getEditableTitleView());
8024705eed4421d3b00923b56062765206dea21387eDake Gu        setupNextImeOptions(vh.getEditableDescriptionView());
8034705eed4421d3b00923b56062765206dea21387eDake Gu    }
8044705eed4421d3b00923b56062765206dea21387eDake Gu
8054705eed4421d3b00923b56062765206dea21387eDake Gu    private void setupNextImeOptions(EditText edit) {
8064705eed4421d3b00923b56062765206dea21387eDake Gu        if (edit != null) {
8074705eed4421d3b00923b56062765206dea21387eDake Gu            edit.setImeOptions(EditorInfo.IME_ACTION_NEXT);
8084705eed4421d3b00923b56062765206dea21387eDake Gu        }
809c1741246af607f6be2389056da0182c40f938348Dake Gu    }
810c1741246af607f6be2389056da0182c40f938348Dake Gu
81177d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    /**
81277d397d533d04dfec663939692f2e048a072ee5bAlan Viverette     * @deprecated This method is for internal library use only and should not
81377d397d533d04dfec663939692f2e048a072ee5bAlan Viverette     *             be called directly.
81477d397d533d04dfec663939692f2e048a072ee5bAlan Viverette     */
81577d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    @Deprecated
81677d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    public void setEditingMode(ViewHolder vh, GuidedAction action, boolean editing) {
81777d397d533d04dfec663939692f2e048a072ee5bAlan Viverette        if (editing != vh.isInEditing() && isInExpandTransition()) {
81877d397d533d04dfec663939692f2e048a072ee5bAlan Viverette            onEditingModeChange(vh, action, editing);
81977d397d533d04dfec663939692f2e048a072ee5bAlan Viverette        }
82077d397d533d04dfec663939692f2e048a072ee5bAlan Viverette    }
82177d397d533d04dfec663939692f2e048a072ee5bAlan Viverette
822ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void setEditingMode(ViewHolder vh, boolean editing) {
823ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        setEditingMode(vh, editing, true /*withTransition*/);
824ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
825ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
826ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void setEditingMode(ViewHolder vh, boolean editing, boolean withTransition) {
827b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (editing != vh.isInEditing() && !isInExpandTransition()) {
828ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            onEditingModeChange(vh, editing, withTransition);
829c1741246af607f6be2389056da0182c40f938348Dake Gu        }
830c1741246af607f6be2389056da0182c40f938348Dake Gu    }
831c1741246af607f6be2389056da0182c40f938348Dake Gu
832ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
833ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @deprecated Use {@link #onEditingModeChange(ViewHolder, boolean, boolean)}.
834ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
835ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @Deprecated
836c1741246af607f6be2389056da0182c40f938348Dake Gu    protected void onEditingModeChange(ViewHolder vh, GuidedAction action, boolean editing) {
837ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
838ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
839ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
840ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Called when editing mode of an ViewHolder is changed.  Subclass must call
841ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * <code>super.onEditingModeChange(vh,editing,withTransition)</code>.
842ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
843ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param vh                ViewHolder to change editing mode.
844ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param editing           True to enable editing, false to stop editing
845ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param withTransition    True to run expand transiiton, false otherwise.
846ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
847ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @CallSuper
848ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    protected void onEditingModeChange(ViewHolder vh, boolean editing, boolean withTransition) {
849ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        GuidedAction action = vh.getAction();
850c1741246af607f6be2389056da0182c40f938348Dake Gu        TextView titleView = vh.getTitleView();
851c1741246af607f6be2389056da0182c40f938348Dake Gu        TextView descriptionView = vh.getDescriptionView();
852c1741246af607f6be2389056da0182c40f938348Dake Gu        if (editing) {
853c1741246af607f6be2389056da0182c40f938348Dake Gu            CharSequence editTitle = action.getEditTitle();
854c1741246af607f6be2389056da0182c40f938348Dake Gu            if (titleView != null && editTitle != null) {
855c1741246af607f6be2389056da0182c40f938348Dake Gu                titleView.setText(editTitle);
856c1741246af607f6be2389056da0182c40f938348Dake Gu            }
857c1741246af607f6be2389056da0182c40f938348Dake Gu            CharSequence editDescription = action.getEditDescription();
858c1741246af607f6be2389056da0182c40f938348Dake Gu            if (descriptionView != null && editDescription != null) {
859c1741246af607f6be2389056da0182c40f938348Dake Gu                descriptionView.setText(editDescription);
860c1741246af607f6be2389056da0182c40f938348Dake Gu            }
861c1741246af607f6be2389056da0182c40f938348Dake Gu            if (action.isDescriptionEditable()) {
862c1741246af607f6be2389056da0182c40f938348Dake Gu                if (descriptionView != null) {
863c1741246af607f6be2389056da0182c40f938348Dake Gu                    descriptionView.setVisibility(View.VISIBLE);
8649562425bf9bc15281ac27df817141854769c1042Dake Gu                    descriptionView.setInputType(action.getDescriptionEditInputType());
865c1741246af607f6be2389056da0182c40f938348Dake Gu                }
866b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                vh.mEditingMode = EDITING_DESCRIPTION;
867b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (action.isEditable()){
8689562425bf9bc15281ac27df817141854769c1042Dake Gu                if (titleView != null) {
8699562425bf9bc15281ac27df817141854769c1042Dake Gu                    titleView.setInputType(action.getEditInputType());
8709562425bf9bc15281ac27df817141854769c1042Dake Gu                }
871b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                vh.mEditingMode = EDITING_TITLE;
872b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (vh.mActivatorView != null) {
873ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                onEditActivatorView(vh, editing, withTransition);
874b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                vh.mEditingMode = EDITING_ACTIVATOR_VIEW;
875c1741246af607f6be2389056da0182c40f938348Dake Gu            }
876c1741246af607f6be2389056da0182c40f938348Dake Gu        } else {
877c1741246af607f6be2389056da0182c40f938348Dake Gu            if (titleView != null) {
878c1741246af607f6be2389056da0182c40f938348Dake Gu                titleView.setText(action.getTitle());
879c1741246af607f6be2389056da0182c40f938348Dake Gu            }
880c1741246af607f6be2389056da0182c40f938348Dake Gu            if (descriptionView != null) {
881c1741246af607f6be2389056da0182c40f938348Dake Gu                descriptionView.setText(action.getDescription());
882c1741246af607f6be2389056da0182c40f938348Dake Gu            }
883b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            if (vh.mEditingMode == EDITING_DESCRIPTION) {
884c1741246af607f6be2389056da0182c40f938348Dake Gu                if (descriptionView != null) {
8853103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    descriptionView.setVisibility(TextUtils.isEmpty(action.getDescription())
8863103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                            ? View.GONE : View.VISIBLE);
8879562425bf9bc15281ac27df817141854769c1042Dake Gu                    descriptionView.setInputType(action.getDescriptionInputType());
888c1741246af607f6be2389056da0182c40f938348Dake Gu                }
889b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (vh.mEditingMode == EDITING_TITLE) {
8909562425bf9bc15281ac27df817141854769c1042Dake Gu                if (titleView != null) {
8919562425bf9bc15281ac27df817141854769c1042Dake Gu                    titleView.setInputType(action.getInputType());
8929562425bf9bc15281ac27df817141854769c1042Dake Gu                }
893b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            } else if (vh.mEditingMode == EDITING_ACTIVATOR_VIEW) {
894b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (vh.mActivatorView != null) {
895ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    onEditActivatorView(vh, editing, withTransition);
896b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
897c1741246af607f6be2389056da0182c40f938348Dake Gu            }
898b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mEditingMode = EDITING_NONE;
899c1741246af607f6be2389056da0182c40f938348Dake Gu        }
900ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        // call deprecated method for backward compatible
901ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        onEditingModeChange(vh, action, editing);
902ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
903ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
904ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
905ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Animates the view holder's view (or subviews thereof) when the action has had its focus
906ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * state changed.
907ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder associated with the relevant action.
908ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param focused True if the action has become focused, false if it has lost focus.
909ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
910ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onAnimateItemFocused(ViewHolder vh, boolean focused) {
911ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // No animations for this, currently, because the animation is done on
912ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // mSelectorView
913ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
914ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
915ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
916ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Animates the view holder's view (or subviews thereof) when the action has had its press
917ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * state changed.
918ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder associated with the relevant action.
919ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param pressed True if the action has been pressed, false if it has been unpressed.
920ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
921ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onAnimateItemPressed(ViewHolder vh, boolean pressed) {
92266e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        vh.press(pressed);
923ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
924ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
925ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
92619c1329def8d277c914cba46540d24bfde58b2a4Dake Gu     * Resets the view holder's view to unpressed state.
92719c1329def8d277c914cba46540d24bfde58b2a4Dake Gu     * @param vh The view holder associated with the relevant action.
92819c1329def8d277c914cba46540d24bfde58b2a4Dake Gu     */
92919c1329def8d277c914cba46540d24bfde58b2a4Dake Gu    public void onAnimateItemPressedCancelled(ViewHolder vh) {
93066e932ebd959ffe318f0780c5f689bac29b09b50Dake Gu        vh.press(false);
93119c1329def8d277c914cba46540d24bfde58b2a4Dake Gu    }
93219c1329def8d277c914cba46540d24bfde58b2a4Dake Gu
93319c1329def8d277c914cba46540d24bfde58b2a4Dake Gu    /**
93411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Animates the view holder's view (or subviews thereof) when the action has had its check state
93511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * changed. Default implementation calls setChecked() if {@link ViewHolder#getCheckmarkView()}
93611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * is instance of {@link Checkable}.
93711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     *
938ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param vh The view holder associated with the relevant action.
939ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @param checked True if the action has become checked, false if it has become unchecked.
94011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @see #onBindCheckMarkView(ViewHolder, GuidedAction)
941ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
942ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    public void onAnimateItemChecked(ViewHolder vh, boolean checked) {
94311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        if (vh.mCheckmarkView instanceof Checkable) {
94411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            ((Checkable) vh.mCheckmarkView).setChecked(checked);
94511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        }
94611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    }
94711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu
94811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    /**
94911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Sets states of check mark view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}
95011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * when action's checkset Id is other than {@link GuidedAction#NO_CHECK_SET}. Default
95111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * implementation assigns drawable loaded from theme attribute
95211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * {@link android.R.attr#listChoiceIndicatorMultiple} for checkbox or
95311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * {@link android.R.attr#listChoiceIndicatorSingle} for radio button. Subclass rarely needs
95411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * override the method, instead app can provide its own drawable that supports transition
95511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * animations, change theme attributes {@link android.R.attr#listChoiceIndicatorMultiple} and
956ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link android.R.attr#listChoiceIndicatorSingle} in {androidx.leanback.R.
95711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * styleable#LeanbackGuidedStepTheme}.
95811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     *
95911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param vh The view holder associated with the relevant action.
96011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param action The GuidedAction object to bind to.
96111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @see #onAnimateItemChecked(ViewHolder, boolean)
96211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     */
96311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    public void onBindCheckMarkView(ViewHolder vh, GuidedAction action) {
96411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        if (action.getCheckSetId() != GuidedAction.NO_CHECK_SET) {
96511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            vh.mCheckmarkView.setVisibility(View.VISIBLE);
9663103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            int attrId = action.getCheckSetId() == GuidedAction.CHECKBOX_CHECK_SET_ID
9673103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    ? android.R.attr.listChoiceIndicatorMultiple
9683103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    : android.R.attr.listChoiceIndicatorSingle;
96911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            final Context context = vh.mCheckmarkView.getContext();
97011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            Drawable drawable = null;
97111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            TypedValue typedValue = new TypedValue();
97211cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            if (context.getTheme().resolveAttribute(attrId, typedValue, true)) {
97311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu                drawable = ContextCompat.getDrawable(context, typedValue.resourceId);
974ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
97511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            vh.mCheckmarkView.setImageDrawable(drawable);
97611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            if (vh.mCheckmarkView instanceof Checkable) {
97711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu                ((Checkable) vh.mCheckmarkView).setChecked(action.isChecked());
97811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            }
97911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu        } else {
98011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu            vh.mCheckmarkView.setVisibility(View.GONE);
981ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
982ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
983ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
98411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    /**
985b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * Performs binding activator view value to action.  Default implementation supports
986b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * GuidedDatePickerAction, subclass may override to add support of other views.
987b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param vh ViewHolder of activator view.
988b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param action GuidedAction to bind.
989b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
990b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public void onBindActivatorView(ViewHolder vh, GuidedAction action) {
991b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (action instanceof GuidedDatePickerAction) {
992b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
993b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            DatePicker dateView = (DatePicker) vh.mActivatorView;
994b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            dateView.setDatePickerFormat(dateAction.getDatePickerFormat());
995942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            if (dateAction.getMinDate() != Long.MIN_VALUE) {
996942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu                dateView.setMinDate(dateAction.getMinDate());
997942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            }
998942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            if (dateAction.getMaxDate() != Long.MAX_VALUE) {
999942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu                dateView.setMaxDate(dateAction.getMaxDate());
1000942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            }
1001b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            Calendar c = Calendar.getInstance();
1002942f79291db75ccf6ecd0351d23a444a43dd0501Dake Gu            c.setTimeInMillis(dateAction.getDate());
1003b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            dateView.updateDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
1004b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    c.get(Calendar.DAY_OF_MONTH), false);
1005b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
1006b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
1007b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
1008b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
1009b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * Performs updating GuidedAction from activator view.  Default implementation supports
1010b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * GuidedDatePickerAction, subclass may override to add support of other views.
1011b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param vh ViewHolder of activator view.
1012b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @param action GuidedAction to update.
1013b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @return True if value has been updated, false otherwise.
1014b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
1015b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public boolean onUpdateActivatorView(ViewHolder vh, GuidedAction action) {
1016b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (action instanceof GuidedDatePickerAction) {
1017b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
1018b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            DatePicker dateView = (DatePicker) vh.mActivatorView;
1019b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            if (dateAction.getDate() != dateView.getDate()) {
1020b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                dateAction.setDate(dateView.getDate());
1021b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                return true;
1022b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            }
1023b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
1024b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        return false;
1025b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
1026b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
1027b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
1028b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * Sets listener for reporting view being edited.
1029b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     * @hide
1030b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu     */
10318e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas    @RestrictTo(LIBRARY_GROUP)
1032b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    public void setEditListener(EditListener listener) {
1033b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        mEditListener = listener;
1034b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
1035b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
1036ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void onEditActivatorView(final ViewHolder vh, boolean editing, final boolean withTransition) {
1037b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        if (editing) {
1038b0818cc234e9df4312732f95fd6849922bfa0fa1Keyvan Amiri            startExpanded(vh, withTransition);
10390f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            vh.itemView.setFocusable(false);
1040b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mActivatorView.requestFocus();
1041b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mActivatorView.setOnClickListener(new View.OnClickListener() {
1042b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                @Override
1043b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                public void onClick(View v) {
1044b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    if (!isInExpandTransition()) {
1045ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        ((GuidedActionAdapter) getActionsGridView().getAdapter())
1046ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                .performOnActionClick(vh);
1047b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    }
1048b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1049b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            });
1050b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        } else {
1051ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (onUpdateActivatorView(vh, vh.getAction())) {
1052b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (mEditListener != null) {
1053ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    mEditListener.onGuidedActionEditedAndProceed(vh.getAction());
1054b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1055b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            }
10560f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            vh.itemView.setFocusable(true);
1057b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.itemView.requestFocus();
1058ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            startExpanded(null, withTransition);
1059b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu            vh.mActivatorView.setOnClickListener(null);
10600f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu            vh.mActivatorView.setClickable(false);
1061b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        }
1062b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    }
1063b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu
1064b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu    /**
106511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Sets states of chevron view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}.
106611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * Subclass may override.
106711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     *
106811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param vh The view holder associated with the relevant action.
106911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     * @param action The GuidedAction object to bind to.
107011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu     */
107111cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    public void onBindChevronView(ViewHolder vh, GuidedAction action) {
1072be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final boolean hasNext = action.hasNext();
1073be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final boolean hasSubActions = action.hasSubActions();
1074be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (hasNext || hasSubActions) {
1075be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.mChevronView.setVisibility(View.VISIBLE);
1076be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.mChevronView.setAlpha(action.isEnabled() ? mEnabledChevronAlpha :
1077be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    mDisabledChevronAlpha);
1078be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            if (hasNext) {
10797a45714d94e3e5566e3879042f7ee2b93eb5c62aDake Gu                float r = mMainView != null
10807a45714d94e3e5566e3879042f7ee2b93eb5c62aDake Gu                        && mMainView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? 180f : 0f;
10817a45714d94e3e5566e3879042f7ee2b93eb5c62aDake Gu                vh.mChevronView.setRotation(r);
1082be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            } else if (action == mExpandedAction) {
1083be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.mChevronView.setRotation(270);
1084be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            } else {
1085be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.mChevronView.setRotation(90);
1086be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
1087be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        } else {
1088be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            vh.mChevronView.setVisibility(View.GONE);
1089be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1090be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1091be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1092be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1093be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
1094ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Expands or collapse the sub actions list view with transition animation
1095be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @param avh When not null, fill sub actions list of this ViewHolder into sub actions list and
1096be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * hide the other items in main list.  When null, collapse the sub actions list.
1097ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @deprecated use {@link #expandAction(GuidedAction, boolean)} and
1098ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * {@link #collapseAction(boolean)}
1099be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
1100ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @Deprecated
1101be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public void setExpandedViewHolder(ViewHolder avh) {
1102ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        expandAction(avh == null ? null : avh.getAction(), isExpandTransitionSupported());
11031ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    }
11041ed9dc77616514e20c51baa67a04adab42e4135eDake Gu
11051ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
11061ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Returns true if it is running an expanding or collapsing transition, false otherwise.
11071ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @return True if it is running an expanding or collapsing transition, false otherwise.
11081ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
11091ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public boolean isInExpandTransition() {
11101ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        return mExpandTransition != null;
11111ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    }
11121ed9dc77616514e20c51baa67a04adab42e4135eDake Gu
11131ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
11141ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Returns if expand/collapse animation is supported.  When this method returns true,
11151ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * {@link #startExpandedTransition(ViewHolder)} will be used.  When this method returns false,
11161ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * {@link #onUpdateExpandedViewHolder(ViewHolder)} will be called.
11171ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @return True if it is running an expanding or collapsing transition, false otherwise.
11181ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
11191ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public boolean isExpandTransitionSupported() {
11201ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        return VERSION.SDK_INT >= 21;
11211ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    }
11221ed9dc77616514e20c51baa67a04adab42e4135eDake Gu
11231ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
11241ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Start transition to expand or collapse GuidedActionStylist.
11251ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @param avh When not null, the GuidedActionStylist expands the sub actions of avh.  When null
11261ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * the GuidedActionStylist will collapse sub actions.
1127ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @deprecated use {@link #expandAction(GuidedAction, boolean)} and
1128ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * {@link #collapseAction(boolean)}
11291ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
1130ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    @Deprecated
11311ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public void startExpandedTransition(ViewHolder avh) {
1132ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        expandAction(avh == null ? null : avh.getAction(), isExpandTransitionSupported());
1133ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1134ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1135ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1136ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Enable or disable using BACK key to collapse sub actions list. Default is enabled.
1137ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1138ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param backToCollapse True to enable using BACK key to collapse sub actions list, false
1139ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *                       to disable.
1140ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasSubActions
1141ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#getSubActions
1142ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1143ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final void setBackKeyToCollapseSubActions(boolean backToCollapse) {
1144ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        mBackToCollapseSubActions = backToCollapse;
1145ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1146ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1147ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1148ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @return True if using BACK key to collapse sub actions list, false otherwise. Default value
1149ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * is true.
1150ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1151ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasSubActions
1152ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#getSubActions
1153ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1154ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final boolean isBackKeyToCollapseSubActions() {
1155ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return mBackToCollapseSubActions;
1156ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1157ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1158ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1159ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Enable or disable using BACK key to collapse {@link GuidedAction} with editable activator
1160ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * view. Default is enabled.
1161ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1162ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param backToCollapse True to enable using BACK key to collapse {@link GuidedAction} with
1163ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *                       editable activator view.
1164ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasEditableActivatorView
1165ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1166ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final void setBackKeyToCollapseActivatorView(boolean backToCollapse) {
1167ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        mBackToCollapseActivatorView = backToCollapse;
1168ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1169ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1170ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1171ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @return True if using BACK key to collapse {@link GuidedAction} with editable activator
1172ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * view, false otherwise. Default value is true.
1173ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1174ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @see GuidedAction#hasEditableActivatorView
1175ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1176ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public final boolean isBackKeyToCollapseActivatorView() {
1177ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return mBackToCollapseActivatorView;
1178ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1179ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1180ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1181ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Expand an action. Do nothing if it is in animation or there is action expanded.
1182ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1183ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param action         Action to expand.
1184ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param withTransition True to run transition animation, false otherwsie.
1185ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1186ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public void expandAction(GuidedAction action, final boolean withTransition) {
1187ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (isInExpandTransition() || mExpandedAction != null) {
1188ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1189ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1190ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        int actionPosition =
1191ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                ((GuidedActionAdapter) getActionsGridView().getAdapter()).indexOf(action);
1192ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (actionPosition < 0) {
1193ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1194ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1195ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        boolean runTransition = isExpandTransitionSupported() && withTransition;
1196ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (!runTransition) {
1197ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            getActionsGridView().setSelectedPosition(actionPosition,
1198ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    new ViewHolderTask() {
1199ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        @Override
1200ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        public void run(RecyclerView.ViewHolder vh) {
1201ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            GuidedActionsStylist.ViewHolder avh =
1202ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    (GuidedActionsStylist.ViewHolder)vh;
1203ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            if (avh.getAction().hasEditableActivatorView()) {
1204ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                setEditingMode(avh, true /*editing*/, false /*withTransition*/);
1205ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            } else {
1206ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                onUpdateExpandedViewHolder(avh);
1207ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            }
1208ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        }
1209ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    });
1210e5d263725fb60aa6a24f2221548afb20d0dc46e1Dake Gu            if (action.hasSubActions()) {
1211e5d263725fb60aa6a24f2221548afb20d0dc46e1Dake Gu                onUpdateSubActionsGridView(action, true);
1212e5d263725fb60aa6a24f2221548afb20d0dc46e1Dake Gu            }
1213ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        } else {
1214ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            getActionsGridView().setSelectedPosition(actionPosition,
1215ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    new ViewHolderTask() {
1216ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        @Override
1217ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        public void run(RecyclerView.ViewHolder vh) {
1218ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            GuidedActionsStylist.ViewHolder avh =
1219ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                    (GuidedActionsStylist.ViewHolder)vh;
1220ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            if (avh.getAction().hasEditableActivatorView()) {
1221ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                setEditingMode(avh, true /*editing*/, true /*withTransition*/);
1222ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            } else {
1223ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                                startExpanded(avh, true);
1224ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                            }
1225ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        }
1226ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    });
1227ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1228ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1229ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1230ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1231ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1232ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Collapse expanded action. Do nothing if it is in animation or there is no action expanded.
1233ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     *
1234ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @param withTransition True to run transition animation, false otherwsie.
1235ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1236ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public void collapseAction(boolean withTransition) {
1237ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (isInExpandTransition() || mExpandedAction == null) {
1238ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1239ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1240ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        boolean runTransition = isExpandTransitionSupported() && withTransition;
1241ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        int actionPosition =
1242ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                ((GuidedActionAdapter) getActionsGridView().getAdapter()).indexOf(mExpandedAction);
1243ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (actionPosition < 0) {
1244ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            return;
1245ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1246ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (mExpandedAction.hasEditableActivatorView()) {
1247ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            setEditingMode(
1248ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    ((ViewHolder) getActionsGridView().findViewHolderForPosition(actionPosition)),
1249ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    false /*editing*/,
1250ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    runTransition);
1251ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        } else {
1252ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            startExpanded(null, runTransition);
1253ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1254ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1255ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1256ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    int getKeyLine() {
1257ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return (int) (mKeyLinePercent * mActionsGridView.getHeight() / 100);
1258ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1259ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1260ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1261ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * Internal method with assumption we already scroll to the new ViewHolder or is currently
1262ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * expanded.
1263ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1264ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void startExpanded(ViewHolder avh, final boolean withTransition) {
12651ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        ViewHolder focusAvh = null; // expand / collapse view holder
12661ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        final int count = mActionsGridView.getChildCount();
12671ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        for (int i = 0; i < count; i++) {
12681ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            ViewHolder vh = (ViewHolder) mActionsGridView
12691ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                    .getChildViewHolder(mActionsGridView.getChildAt(i));
12701ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            if (avh == null && vh.itemView.getVisibility() == View.VISIBLE) {
12711ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                // going to collapse this one.
12721ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                focusAvh = vh;
12731ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                break;
12741ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            } else if (avh != null && vh.getAction() == avh.getAction()) {
12751ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                // going to expand this one.
12761ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                focusAvh = vh;
12771ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                break;
12781ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
12791ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
12801ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        if (focusAvh == null) {
12811ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            // huh?
12821ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            return;
12831ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
1284ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        boolean isExpand = avh != null;
1285b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu        boolean isSubActionTransition = focusAvh.getAction().hasSubActions();
1286ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (withTransition) {
1287ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object set = TransitionHelper.createTransitionSet(false);
1288ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            float slideDistance = isSubActionTransition ? focusAvh.itemView.getHeight()
1289ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    : focusAvh.itemView.getHeight() * 0.5f;
1290ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object slideAndFade = TransitionHelper.createFadeAndShortSlide(
1291ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    Gravity.TOP | Gravity.BOTTOM,
1292ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    slideDistance);
1293ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.setEpicenterCallback(slideAndFade, new TransitionEpicenterCallback() {
1294ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                Rect mRect = new Rect();
1295ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                @Override
1296ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                public Rect onGetEpicenter(Object transition) {
1297ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    int centerY = getKeyLine();
1298ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    int centerX = 0;
1299ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    mRect.set(centerX, centerY, centerX, centerY);
1300ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    return mRect;
1301b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1302ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            });
1303ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object changeFocusItemTransform = TransitionHelper.createChangeTransform();
1304ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object changeFocusItemBounds = TransitionHelper.createChangeBounds(false);
13053103f63e99d47573823957f7aa34308555873221Aurimas Liutikas            Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN
13063103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                    | TransitionHelper.FADE_OUT);
1307ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            Object changeGridBounds = TransitionHelper.createChangeBounds(false);
1308ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (avh == null) {
1309ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(slideAndFade, 150);
1310ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemTransform, 100);
1311ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemBounds, 100);
1312ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeGridBounds, 100);
13131ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            } else {
1314ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(fade, 100);
1315ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeGridBounds, 50);
1316ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemTransform, 50);
1317ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.setStartDelay(changeFocusItemBounds, 50);
13181ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
1319ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            for (int i = 0; i < count; i++) {
1320ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                ViewHolder vh = (ViewHolder) mActionsGridView
1321ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        .getChildViewHolder(mActionsGridView.getChildAt(i));
1322ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                if (vh == focusAvh) {
1323ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    // going to expand/collapse this one.
1324ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    if (isSubActionTransition) {
1325ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        TransitionHelper.include(changeFocusItemTransform, vh.itemView);
1326ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        TransitionHelper.include(changeFocusItemBounds, vh.itemView);
1327ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    }
1328ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                } else {
1329ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    // going to slide this item to top / bottom.
1330ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    TransitionHelper.include(slideAndFade, vh.itemView);
1331ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    TransitionHelper.exclude(fade, vh.itemView, true);
1332ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                }
1333ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            }
1334ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.include(changeGridBounds, mSubActionsGridView);
1335ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.include(changeGridBounds, mSubActionsBackground);
1336ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransition(set, slideAndFade);
1337ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            // note that we don't run ChangeBounds for activating view due to the rounding problem
1338ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            // of multiple level views ChangeBounds animation causing vertical jittering.
1339ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (isSubActionTransition) {
1340ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.addTransition(set, changeFocusItemTransform);
1341ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                TransitionHelper.addTransition(set, changeFocusItemBounds);
13421ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
1343ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransition(set, fade);
1344ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransition(set, changeGridBounds);
1345ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            mExpandTransition = set;
1346ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.addTransitionListener(mExpandTransition, new TransitionListener() {
13471ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                @Override
1348ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                public void onTransitionEnd(Object transition) {
1349ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    mExpandTransition = null;
13501ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                }
13511ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            });
1352ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (isExpand && isSubActionTransition) {
1353ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // To expand sub actions, move original position of sub actions to bottom of item
1354ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                int startY = avh.itemView.getBottom();
1355ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                mSubActionsGridView.offsetTopAndBottom(startY - mSubActionsGridView.getTop());
1356ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                mSubActionsBackground.offsetTopAndBottom(startY - mSubActionsBackground.getTop());
1357ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            }
1358ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            TransitionHelper.beginDelayedTransition(mMainView, mExpandTransition);
13591ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
13601ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        onUpdateExpandedViewHolder(avh);
1361ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        if (isSubActionTransition) {
1362ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            onUpdateSubActionsGridView(focusAvh.getAction(), isExpand);
1363ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        }
1364be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1365be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1366be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
1367be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return True if sub actions list is expanded.
1368be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
1369be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public boolean isSubActionsExpanded() {
1370ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu        return mExpandedAction != null && mExpandedAction.hasSubActions();
1371ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1372ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1373ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    /**
1374ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     * @return True if there is {@link #getExpandedAction()} is not null, false otherwise.
1375ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu     */
1376ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    public boolean isExpanded() {
1377be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mExpandedAction != null;
1378be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1379be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1380be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    /**
1381be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     * @return Current expanded GuidedAction or null if not expanded.
1382be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu     */
1383be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    public GuidedAction getExpandedAction() {
1384be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        return mExpandedAction;
1385be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1386be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
13871ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    /**
13881ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * Expand or collapse GuidedActionStylist.
13891ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * @param avh When not null, the GuidedActionStylist expands the sub actions of avh.  When null
13901ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     * the GuidedActionStylist will collapse sub actions.
13911ed9dc77616514e20c51baa67a04adab42e4135eDake Gu     */
13921ed9dc77616514e20c51baa67a04adab42e4135eDake Gu    public void onUpdateExpandedViewHolder(ViewHolder avh) {
1393b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri
1394b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // Note about setting the prune child flag back & forth here: without this, the actions that
1395b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // go off the screen from the top or bottom become invisible forever. This is because once
1396b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // an action is expanded, it takes more space which in turn kicks out some other actions
1397b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // off of the screen. Once, this action is collapsed (after the second click) and the
1398b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // visibility flag is set back to true for all existing actions,
1399b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // the off-the-screen actions are pruned from the view, thus
1400b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri        // could not be accessed, had we not disabled pruning prior to this.
14011ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        if (avh == null) {
14021ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            mExpandedAction = null;
1403b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri            mActionsGridView.setPruneChild(true);
14041ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        } else if (avh.getAction() != mExpandedAction) {
14051ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            mExpandedAction = avh.getAction();
1406b2121d7935303972c0d515c29b9771c74311c8baKeyvan Amiri            mActionsGridView.setPruneChild(false);
14071ed9dc77616514e20c51baa67a04adab42e4135eDake Gu        }
1408fb23f1271e21761bb523948d9ea9c60c42ae7251Dake Gu        // In expanding mode, notifyItemChange on expanded item will reset the translationY by
1409fb23f1271e21761bb523948d9ea9c60c42ae7251Dake Gu        // the default ItemAnimator.  So disable ItemAnimation in expanding mode.
1410fb23f1271e21761bb523948d9ea9c60c42ae7251Dake Gu        mActionsGridView.setAnimateChildLayout(false);
1411be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        final int count = mActionsGridView.getChildCount();
1412be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        for (int i = 0; i < count; i++) {
1413be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            ViewHolder vh = (ViewHolder) mActionsGridView
1414be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                    .getChildViewHolder(mActionsGridView.getChildAt(i));
1415be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            updateChevronAndVisibility(vh);
1416be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1417ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    }
1418ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu
1419ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu    void onUpdateSubActionsGridView(GuidedAction action, boolean expand) {
1420be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (mSubActionsGridView != null) {
1421ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            ViewGroup.MarginLayoutParams lp =
1422ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    (ViewGroup.MarginLayoutParams) mSubActionsGridView.getLayoutParams();
1423ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            GuidedActionAdapter adapter = (GuidedActionAdapter) mSubActionsGridView.getAdapter();
1424ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            if (expand) {
1425ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // set to negative value so GuidedActionRelativeLayout will override with
1426ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // keyLine percentage.
1427ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                lp.topMargin = -2;
14281ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                lp.height = ViewGroup.MarginLayoutParams.MATCH_PARENT;
14291ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setLayoutParams(lp);
14301ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setVisibility(View.VISIBLE);
1431fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                mSubActionsBackground.setVisibility(View.VISIBLE);
14321ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.requestFocus();
1433ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                adapter.setActions(action.getSubActions());
1434ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu            } else {
1435ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // set to explicit value, which will disable the keyLine percentage calculation
1436ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                // in GuidedRelativeLayout.
1437ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                int actionPosition = ((GuidedActionAdapter) mActionsGridView.getAdapter())
1438ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        .indexOf(action);
1439ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                lp.topMargin = mActionsGridView.getLayoutManager()
1440ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                        .findViewByPosition(actionPosition).getBottom();
1441ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                lp.height = 0;
14421ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setVisibility(View.INVISIBLE);
1443fa4d2cddf2cb9619088153a1fe07d09203d792faDake Gu                mSubActionsBackground.setVisibility(View.INVISIBLE);
14441ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mSubActionsGridView.setLayoutParams(lp);
1445ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                adapter.setActions(Collections.EMPTY_LIST);
14461ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                mActionsGridView.requestFocus();
14471ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            }
1448be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1449be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    }
1450be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu
1451be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu    private void updateChevronAndVisibility(ViewHolder vh) {
1452be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (!vh.isSubAction()) {
14531ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            if (mExpandedAction == null) {
14541ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                vh.itemView.setVisibility(View.VISIBLE);
14551ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                vh.itemView.setTranslationY(0);
1456b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (vh.mActivatorView != null) {
14570f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu                    vh.setActivated(false);
1458b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
14591ed9dc77616514e20c51baa67a04adab42e4135eDake Gu            } else if (vh.getAction() == mExpandedAction) {
1460be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.itemView.setVisibility(View.VISIBLE);
1461b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                if (vh.getAction().hasSubActions()) {
1462ae746be7c46297b910a99c07697e33e3a5fd7facDake Gu                    vh.itemView.setTranslationY(getKeyLine() - vh.itemView.getBottom());
1463b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                } else if (vh.mActivatorView != null) {
1464b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                    vh.itemView.setTranslationY(0);
14650f96ae4965103bade4bebe7776b2ee35cd603112Dake Gu                    vh.setActivated(true);
1466b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu                }
1467be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            } else {
1468be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu                vh.itemView.setVisibility(View.INVISIBLE);
14691ed9dc77616514e20c51baa67a04adab42e4135eDake Gu                vh.itemView.setTranslationY(0);
1470be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            }
1471be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
1472be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        if (vh.mChevronView != null) {
1473be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu            onBindChevronView(vh, vh.getAction());
1474be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu        }
147511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu    }
147611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu
1477ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /*
1478ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1479ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * FragmentAnimationProvider overrides
1480ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1481ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1482ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1483ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
1484ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * {@inheritDoc}
1485ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1486ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    @Override
14874158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    public void onImeAppearing(@NonNull List<Animator> animators) {
14884158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    }
14894158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing
14904158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    /**
14914158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing     * {@inheritDoc}
14924158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing     */
14934158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    @Override
14944158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    public void onImeDisappearing(@NonNull List<Animator> animators) {
14954158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing    }
14964158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing
1497ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /*
1498ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1499ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * Private methods
1500ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * ==========================================
1501ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1502ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1503ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private float getFloat(Context ctx, TypedValue typedValue, int attrId) {
1504ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        ctx.getTheme().resolveAttribute(attrId, typedValue, true);
1505ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // Android resources don't have a native float type, so we have to use strings.
1506ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return Float.valueOf(ctx.getResources().getString(typedValue.resourceId));
1507ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1508ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1509ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int getInteger(Context ctx, TypedValue typedValue, int attrId) {
1510ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        ctx.getTheme().resolveAttribute(attrId, typedValue, true);
1511ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return ctx.getResources().getInteger(typedValue.resourceId);
1512ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1513ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1514ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int getDimension(Context ctx, TypedValue typedValue, int attrId) {
1515ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        ctx.getTheme().resolveAttribute(attrId, typedValue, true);
1516ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return ctx.getResources().getDimensionPixelSize(typedValue.resourceId);
1517ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1518ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1519ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private boolean setIcon(final ImageView iconView, GuidedAction action) {
1520ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        Drawable icon = null;
1521ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        if (iconView != null) {
1522ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            icon = action.getIcon();
1523ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            if (icon != null) {
1524162b21598d9f4fd49748b3c7e27501fe1277210dChristopher Lane                // setImageDrawable resets the drawable's level unless we set the view level first.
1525162b21598d9f4fd49748b3c7e27501fe1277210dChristopher Lane                iconView.setImageLevel(icon.getLevel());
1526ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                iconView.setImageDrawable(icon);
1527ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                iconView.setVisibility(View.VISIBLE);
1528ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            } else {
1529ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing                iconView.setVisibility(View.GONE);
1530ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing            }
1531ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        }
1532ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return icon != null;
1533ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1534ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1535ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    /**
1536ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     * @return the max height in pixels the description can be such that the
1537ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     *         action nicely takes up the entire screen.
1538ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing     */
1539ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    private int getDescriptionMaxHeight(Context context, TextView title) {
1540ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // The 2 multiplier on the title height calculation is a
1541ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // conservative estimate for font padding which can not be
1542ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        // calculated at this stage since the view hasn't been rendered yet.
1543ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing        return (int)(mDisplayHeight - 2*mVerticalPadding - 2*mTitleMaxLines*title.getLineHeight());
1544ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing    }
1545ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing
1546ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing}
1547