• 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");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.setupwizardlib;
18 
19 import android.annotation.TargetApi;
20 import android.content.Context;
21 import android.content.res.ColorStateList;
22 import android.content.res.TypedArray;
23 import android.graphics.drawable.Drawable;
24 import android.os.Build;
25 import android.os.Build.VERSION_CODES;
26 import android.util.AttributeSet;
27 import android.view.InflateException;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.view.ViewStub;
32 import android.widget.ImageView;
33 import android.widget.ProgressBar;
34 import android.widget.ScrollView;
35 import android.widget.TextView;
36 
37 import com.android.setupwizardlib.view.StatusBarBackgroundLayout;
38 
39 /**
40  * Layout for the GLIF theme used in Setup Wizard for N.
41  *
42  * <p>Example usage:
43  * <pre>{@code
44  * &lt;com.android.setupwizardlib.GlifLayout
45  *     xmlns:android="http://schemas.android.com/apk/res/android"
46  *     xmlns:app="http://schemas.android.com/apk/res-auto"
47  *     android:layout_width="match_parent"
48  *     android:layout_height="match_parent"
49  *     android:icon="@drawable/my_icon"
50  *     app:suwHeaderText="@string/my_title">
51  *
52  *     &lt;!-- Content here -->
53  *
54  * &lt;/com.android.setupwizardlib.GlifLayout>
55  * }</pre>
56  */
57 public class GlifLayout extends TemplateLayout {
58 
59     private static final String TAG = "GlifLayout";
60 
61     private ColorStateList mPrimaryColor;
62 
GlifLayout(Context context)63     public GlifLayout(Context context) {
64         this(context, 0, 0);
65     }
66 
GlifLayout(Context context, int template)67     public GlifLayout(Context context, int template) {
68         this(context, template, 0);
69     }
70 
GlifLayout(Context context, int template, int containerId)71     public GlifLayout(Context context, int template, int containerId) {
72         super(context, template, containerId);
73         init(null, R.attr.suwLayoutTheme);
74     }
75 
GlifLayout(Context context, AttributeSet attrs)76     public GlifLayout(Context context, AttributeSet attrs) {
77         super(context, attrs);
78         init(attrs, R.attr.suwLayoutTheme);
79     }
80 
81     @TargetApi(VERSION_CODES.HONEYCOMB)
GlifLayout(Context context, AttributeSet attrs, int defStyleAttr)82     public GlifLayout(Context context, AttributeSet attrs, int defStyleAttr) {
83         super(context, attrs, defStyleAttr);
84         init(attrs, defStyleAttr);
85     }
86 
87     // All the constructors delegate to this init method. The 3-argument constructor is not
88     // available in LinearLayout before v11, so call super with the exact same arguments.
init(AttributeSet attrs, int defStyleAttr)89     private void init(AttributeSet attrs, int defStyleAttr) {
90         final TypedArray a = getContext().obtainStyledAttributes(attrs,
91                 R.styleable.SuwGlifLayout, defStyleAttr, 0);
92 
93         final Drawable icon = a.getDrawable(R.styleable.SuwGlifLayout_android_icon);
94         if (icon != null) {
95             setIcon(icon);
96         }
97 
98         // Set the header color
99         final ColorStateList headerColor =
100                 a.getColorStateList(R.styleable.SuwGlifLayout_suwHeaderColor);
101         if (headerColor != null) {
102             setHeaderColor(headerColor);
103         }
104 
105 
106         // Set the header text
107         final CharSequence headerText =
108                 a.getText(R.styleable.SuwGlifLayout_suwHeaderText);
109         if (headerText != null) {
110             setHeaderText(headerText);
111         }
112 
113         final ColorStateList primaryColor =
114                 a.getColorStateList(R.styleable.SuwGlifLayout_android_colorPrimary);
115         setPrimaryColor(primaryColor);
116 
117         a.recycle();
118     }
119 
120     @Override
onInflateTemplate(LayoutInflater inflater, int template)121     protected View onInflateTemplate(LayoutInflater inflater, int template) {
122         if (template == 0) {
123             template = R.layout.suw_glif_template;
124         }
125         try {
126             return super.onInflateTemplate(inflater, template);
127         } catch (RuntimeException e) {
128             // Versions before M throws RuntimeException for unsuccessful attribute resolution
129             // Versions M+ will throw an InflateException (which extends from RuntimeException)
130             throw new InflateException("Unable to inflate layout. Are you using "
131                     + "@style/SuwThemeGlif (or its descendant) as your theme?", e);
132         }
133     }
134 
135     @Override
findContainer(int containerId)136     protected ViewGroup findContainer(int containerId) {
137         if (containerId == 0) {
138             containerId = R.id.suw_layout_content;
139         }
140         return super.findContainer(containerId);
141     }
142 
143     /**
144      * Same as {@link android.view.View#findViewById(int)}, but may include views that are managed
145      * by this view but not currently added to the view hierarchy. e.g. recycler view or list view
146      * headers that are not currently shown.
147      */
findManagedViewById(int id)148     protected View findManagedViewById(int id) {
149         return findViewById(id);
150     }
151 
getScrollView()152     public ScrollView getScrollView() {
153         final View view = findManagedViewById(R.id.suw_scroll_view);
154         return view instanceof ScrollView ? (ScrollView) view : null;
155     }
156 
getHeaderTextView()157     public TextView getHeaderTextView() {
158         return (TextView) findManagedViewById(R.id.suw_layout_title);
159     }
160 
setHeaderText(int title)161     public void setHeaderText(int title) {
162         setHeaderText(getContext().getResources().getText(title));
163     }
164 
setHeaderText(CharSequence title)165     public void setHeaderText(CharSequence title) {
166         final TextView titleView = getHeaderTextView();
167         if (titleView != null) {
168             titleView.setText(title);
169         }
170     }
171 
getHeaderText()172     public CharSequence getHeaderText() {
173         final TextView titleView = getHeaderTextView();
174         return titleView != null ? titleView.getText() : null;
175     }
176 
setHeaderColor(ColorStateList color)177     public void setHeaderColor(ColorStateList color) {
178         final TextView titleView = getHeaderTextView();
179         if (titleView != null) {
180             titleView.setTextColor(color);
181         }
182     }
183 
getHeaderColor()184     public ColorStateList getHeaderColor() {
185         final TextView titleView = getHeaderTextView();
186         return titleView != null ? titleView.getTextColors() : null;
187     }
188 
setIcon(Drawable icon)189     public void setIcon(Drawable icon) {
190         final ImageView iconView = getIconView();
191         if (iconView != null) {
192             iconView.setImageDrawable(icon);
193         }
194     }
195 
getIcon()196     public Drawable getIcon() {
197         final ImageView iconView = getIconView();
198         return iconView != null ? iconView.getDrawable() : null;
199     }
200 
getIconView()201     protected ImageView getIconView() {
202         return (ImageView) findManagedViewById(R.id.suw_layout_icon);
203     }
204 
setPrimaryColor(ColorStateList color)205     public void setPrimaryColor(ColorStateList color) {
206         mPrimaryColor = color;
207         setGlifPatternColor(color);
208         setProgressBarColor(color);
209     }
210 
getPrimaryColor()211     public ColorStateList getPrimaryColor() {
212         return mPrimaryColor;
213     }
214 
setGlifPatternColor(ColorStateList color)215     private void setGlifPatternColor(ColorStateList color) {
216         if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
217             setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
218             final View patternBg = findManagedViewById(R.id.suw_pattern_bg);
219             if (patternBg != null) {
220                 final GlifPatternDrawable background =
221                         new GlifPatternDrawable(color.getDefaultColor());
222                 if (patternBg instanceof StatusBarBackgroundLayout) {
223                     ((StatusBarBackgroundLayout) patternBg).setStatusBarBackground(background);
224                 } else {
225                     patternBg.setBackground(background);
226                 }
227             }
228         }
229     }
230 
isProgressBarShown()231     public boolean isProgressBarShown() {
232         final View progressBar = findManagedViewById(R.id.suw_layout_progress);
233         return progressBar != null && progressBar.getVisibility() == View.VISIBLE;
234     }
235 
setProgressBarShown(boolean shown)236     public void setProgressBarShown(boolean shown) {
237         if (shown) {
238             View progressBar = getProgressBar();
239             if (progressBar != null) {
240                 progressBar.setVisibility(View.VISIBLE);
241             }
242         } else {
243             View progressBar = peekProgressBar();
244             if (progressBar != null) {
245                 progressBar.setVisibility(View.GONE);
246             }
247         }
248     }
249 
250     /**
251      * Gets the progress bar in the layout. If the progress bar has not been used before, it will be
252      * installed (i.e. inflated from its view stub).
253      *
254      * @return The progress bar of this layout. May be null only if the template used doesn't have a
255      *         progress bar built-in.
256      */
getProgressBar()257     private ProgressBar getProgressBar() {
258         final View progressBar = peekProgressBar();
259         if (progressBar == null) {
260             final ViewStub progressBarStub =
261                     (ViewStub) findManagedViewById(R.id.suw_layout_progress_stub);
262             if (progressBarStub != null) {
263                 progressBarStub.inflate();
264             }
265             setProgressBarColor(mPrimaryColor);
266         }
267         return peekProgressBar();
268     }
269 
270     /**
271      * Gets the progress bar in the layout only if it has been installed.
272      * {@link #setProgressBarShown(boolean)} should be called before this to ensure the progress bar
273      * is set up correctly.
274      *
275      * @return The progress bar of this layout, or null if the progress bar is not installed. The
276      *         null case can happen either if {@link #setProgressBarShown(boolean)} with true was
277      *         not called before this, or if the template does not contain a progress bar.
278      */
peekProgressBar()279     public ProgressBar peekProgressBar() {
280         return (ProgressBar) findManagedViewById(R.id.suw_layout_progress);
281     }
282 
setProgressBarColor(ColorStateList color)283     private void setProgressBarColor(ColorStateList color) {
284         if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
285             final ProgressBar bar = peekProgressBar();
286             if (bar != null) {
287                 bar.setIndeterminateTintList(color);
288             }
289         }
290     }
291 }
292