• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package android.support.v17.leanback.widget;
15 
16 import android.animation.Animator;
17 import android.animation.AnimatorInflater;
18 import android.content.Context;
19 import android.graphics.drawable.Drawable;
20 import android.support.annotation.NonNull;
21 import android.support.v17.leanback.R;
22 import android.text.TextUtils;
23 import android.util.TypedValue;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.ImageView;
28 import android.widget.TextView;
29 
30 import java.util.List;
31 
32 /**
33  * GuidanceStylist is used within a {@link android.support.v17.leanback.app.GuidedStepFragment}
34  * to display contextual information for the decision(s) required at that step.
35  * <p>
36  * Many aspects of the base GuidanceStylist can be customized through theming; see the theme
37  * attributes below. Note that these attributes are not set on individual elements in layout
38  * XML, but instead would be set in a custom theme. See
39  * <a href="http://developer.android.com/guide/topics/ui/themes.html">Styles and Themes</a>
40  * for more information.
41  * <p>
42  * If these hooks are insufficient, this class may also be subclassed. Subclasses
43  * may wish to override the {@link #onProvideLayoutId} method to change the layout file used to
44  * display the guidance; more complex layouts may be supported by also providing a subclass of
45  * {@link GuidanceStylist.Guidance} with extra fields.
46  * <p>
47  * Note: If an alternate layout is provided, the following view IDs should be used to refer to base
48  * elements:
49  * <ul>
50  * <li>{@link android.support.v17.leanback.R.id#guidance_title}</li>
51  * <li>{@link android.support.v17.leanback.R.id#guidance_description}</li>
52  * <li>{@link android.support.v17.leanback.R.id#guidance_breadcrumb}</li>
53  * <li>{@link android.support.v17.leanback.R.id#guidance_icon}</li>
54  * </ul><p>
55  * View IDs are allowed to be missing, in which case the corresponding views will be null.
56  *
57  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
58  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
59  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceContainerStyle
60  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceTitleStyle
61  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceDescriptionStyle
62  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceBreadcrumbStyle
63  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceIconStyle
64  * @see android.support.v17.leanback.app.GuidedStepFragment
65  * @see GuidanceStylist.Guidance
66  */
67 public class GuidanceStylist implements FragmentAnimationProvider {
68 
69     /**
70      * A data class representing contextual information for a {@link
71      * android.support.v17.leanback.app.GuidedStepFragment}. Guidance consists of a short title,
72      * a longer description, a breadcrumb to help with global navigation (often indicating where
73      * the back button will lead), and an optional icon.  All this information is intended to
74      * provide users with the appropriate context to make the decision(s) required by the current
75      * step.
76      * <p>
77      * Clients may provide a subclass of this if they wish to remember auxiliary data for use in
78      * a customized GuidanceStylist.
79      */
80     public static class Guidance {
81         private final String mTitle;
82         private final String mDescription;
83         private final String mBreadcrumb;
84         private final Drawable mIconDrawable;
85 
86         /**
87          * Constructs a Guidance object with the specified title, description, breadcrumb, and
88          * icon drawable.
89          * @param title The title for the current guided step.
90          * @param description The description for the current guided step.
91          * @param breadcrumb The breadcrumb for the current guided step.
92          * @param icon The icon drawable representing the current guided step.
93          */
Guidance(String title, String description, String breadcrumb, Drawable icon)94         public Guidance(String title, String description, String breadcrumb, Drawable icon) {
95             mBreadcrumb = breadcrumb;
96             mTitle = title;
97             mDescription = description;
98             mIconDrawable = icon;
99         }
100 
101         /**
102          * Returns the title specified when this Guidance was constructed.
103          * @return The title for this Guidance.
104          */
getTitle()105         public String getTitle() {
106             return mTitle;
107         }
108 
109         /**
110          * Returns the description specified when this Guidance was constructed.
111          * @return The description for this Guidance.
112          */
getDescription()113         public String getDescription() {
114             return mDescription;
115         }
116 
117         /**
118          * Returns the breadcrumb specified when this Guidance was constructed.
119          * @return The breadcrumb for this Guidance.
120          */
getBreadcrumb()121         public String getBreadcrumb() {
122             return mBreadcrumb;
123         }
124 
125         /**
126          * Returns the icon drawable specified when this Guidance was constructed.
127          * @return The icon for this Guidance.
128          */
getIconDrawable()129         public Drawable getIconDrawable() {
130             return mIconDrawable;
131         }
132     }
133 
134     private TextView mTitleView;
135     private TextView mDescriptionView;
136     private TextView mBreadcrumbView;
137     private ImageView mIconView;
138     private View mGuidanceContainer;
139 
140     /**
141      * Creates an appropriately configured view for the given Guidance, using the provided
142      * inflater and container.
143      * <p>
144      * <i>Note: Does not actually add the created view to the container; the caller should do
145      * this.</i>
146      * @param inflater The layout inflater to be used when constructing the view.
147      * @param container The view group to be passed in the call to
148      * <code>LayoutInflater.inflate</code>.
149      * @param guidance The guidance data for the view.
150      * @return The view to be added to the caller's view hierarchy.
151      */
onCreateView( final LayoutInflater inflater, ViewGroup container, Guidance guidance)152     public View onCreateView(
153             final LayoutInflater inflater, ViewGroup container, Guidance guidance) {
154 
155         View guidanceView = inflater.inflate(onProvideLayoutId(), container, false);
156         mTitleView = (TextView) guidanceView.findViewById(R.id.guidance_title);
157         mBreadcrumbView = (TextView) guidanceView.findViewById(R.id.guidance_breadcrumb);
158         mDescriptionView = (TextView) guidanceView.findViewById(R.id.guidance_description);
159         mIconView = (ImageView) guidanceView.findViewById(R.id.guidance_icon);
160         mGuidanceContainer = guidanceView.findViewById(R.id.guidance_container);
161 
162         // We allow any of the cached subviews to be null, so that subclasses can choose not to
163         // display a particular piece of information.
164         if (mTitleView != null) {
165             mTitleView.setText(guidance.getTitle());
166         }
167 
168         if (mBreadcrumbView != null) {
169             mBreadcrumbView.setText(guidance.getBreadcrumb());
170         }
171 
172         if (mDescriptionView != null) {
173             mDescriptionView.setText(guidance.getDescription());
174         }
175 
176         if (mIconView != null) {
177             if (guidance.getIconDrawable() != null) {
178                 mIconView.setImageDrawable(guidance.getIconDrawable());
179             } else {
180                 mIconView.setVisibility(View.GONE);
181             }
182         }
183 
184         if (mGuidanceContainer != null) {
185             CharSequence contentDescription = mGuidanceContainer.getContentDescription();
186             if (TextUtils.isEmpty(contentDescription)) {
187                 mGuidanceContainer.setContentDescription(new StringBuilder()
188                         .append(guidance.getBreadcrumb()).append('\n')
189                         .append(guidance.getTitle()).append('\n')
190                         .append(guidance.getDescription())
191                         .toString());
192             }
193         }
194 
195         return guidanceView;
196     }
197 
198     /**
199      * Called when destroy the View created by GuidanceStylist.
200      */
onDestroyView()201     public void onDestroyView() {
202         mBreadcrumbView = null;
203         mDescriptionView = null;
204         mIconView = null;
205         mTitleView = null;
206     }
207 
208     /**
209      * Provides the resource ID of the layout defining the guidance view. Subclasses may override
210      * to provide their own customized layouts. The base implementation returns
211      * {@link android.support.v17.leanback.R.layout#lb_guidance}. If overridden, the substituted
212      * layout should contain matching IDs for any views that should be managed by the base class;
213      * this can be achieved by starting with a copy of the base layout file.
214      * @return The resource ID of the layout to be inflated to define the guidance view.
215      */
onProvideLayoutId()216     public int onProvideLayoutId() {
217         return R.layout.lb_guidance;
218     }
219 
220     /**
221      * Returns the view displaying the title of the guidance.
222      * @return The text view object for the title.
223      */
getTitleView()224     public TextView getTitleView() {
225         return mTitleView;
226     }
227 
228     /**
229      * Returns the view displaying the description of the guidance.
230      * @return The text view object for the description.
231      */
getDescriptionView()232     public TextView getDescriptionView() {
233         return mDescriptionView;
234     }
235 
236     /**
237      * Returns the view displaying the breadcrumb of the guidance.
238      * @return The text view object for the breadcrumb.
239      */
getBreadcrumbView()240     public TextView getBreadcrumbView() {
241         return mBreadcrumbView;
242     }
243 
244     /**
245      * Returns the view displaying the icon of the guidance.
246      * @return The image view object for the icon.
247      */
getIconView()248     public ImageView getIconView() {
249         return mIconView;
250     }
251 
252     /**
253      * {@inheritDoc}
254      */
255     @Override
onImeAppearing(@onNull List<Animator> animators)256     public void onImeAppearing(@NonNull List<Animator> animators) {
257     }
258 
259     /**
260      * {@inheritDoc}
261      */
262     @Override
onImeDisappearing(@onNull List<Animator> animators)263     public void onImeDisappearing(@NonNull List<Animator> animators) {
264     }
265 
266 }
267