• 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.ColorDrawable;
24 import android.graphics.drawable.Drawable;
25 import android.os.Build;
26 import android.os.Build.VERSION_CODES;
27 import android.support.annotation.LayoutRes;
28 import android.support.annotation.NonNull;
29 import android.support.annotation.Nullable;
30 import android.util.AttributeSet;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.view.ViewStub;
35 import android.widget.ProgressBar;
36 import android.widget.ScrollView;
37 import android.widget.TextView;
38 
39 import com.android.setupwizardlib.template.ButtonFooterMixin;
40 import com.android.setupwizardlib.template.ColoredHeaderMixin;
41 import com.android.setupwizardlib.template.HeaderMixin;
42 import com.android.setupwizardlib.template.IconMixin;
43 import com.android.setupwizardlib.template.ProgressBarMixin;
44 import com.android.setupwizardlib.template.RequireScrollMixin;
45 import com.android.setupwizardlib.template.ScrollViewScrollHandlingDelegate;
46 import com.android.setupwizardlib.view.StatusBarBackgroundLayout;
47 
48 /**
49  * Layout for the GLIF theme used in Setup Wizard for N.
50  *
51  * <p>Example usage:
52  * <pre>{@code
53  * &lt;com.android.setupwizardlib.GlifLayout
54  *     xmlns:android="http://schemas.android.com/apk/res/android"
55  *     xmlns:app="http://schemas.android.com/apk/res-auto"
56  *     android:layout_width="match_parent"
57  *     android:layout_height="match_parent"
58  *     android:icon="@drawable/my_icon"
59  *     app:suwHeaderText="@string/my_title">
60  *
61  *     &lt;!-- Content here -->
62  *
63  * &lt;/com.android.setupwizardlib.GlifLayout>
64  * }</pre>
65  */
66 public class GlifLayout extends TemplateLayout {
67 
68     private static final String TAG = "GlifLayout";
69 
70     private ColorStateList mPrimaryColor;
71 
72     private boolean mBackgroundPatterned = true;
73 
74     /**
75      * The color of the background. If null, the color will inherit from mPrimaryColor.
76      */
77     @Nullable
78     private ColorStateList mBackgroundBaseColor;
79 
80     private boolean mLayoutFullscreen = true;
81 
GlifLayout(Context context)82     public GlifLayout(Context context) {
83         this(context, 0, 0);
84     }
85 
GlifLayout(Context context, int template)86     public GlifLayout(Context context, int template) {
87         this(context, template, 0);
88     }
89 
GlifLayout(Context context, int template, int containerId)90     public GlifLayout(Context context, int template, int containerId) {
91         super(context, template, containerId);
92         init(null, R.attr.suwLayoutTheme);
93     }
94 
GlifLayout(Context context, AttributeSet attrs)95     public GlifLayout(Context context, AttributeSet attrs) {
96         super(context, attrs);
97         init(attrs, R.attr.suwLayoutTheme);
98     }
99 
100     @TargetApi(VERSION_CODES.HONEYCOMB)
GlifLayout(Context context, AttributeSet attrs, int defStyleAttr)101     public GlifLayout(Context context, AttributeSet attrs, int defStyleAttr) {
102         super(context, attrs, defStyleAttr);
103         init(attrs, defStyleAttr);
104     }
105 
106     // All the constructors delegate to this init method. The 3-argument constructor is not
107     // available in LinearLayout before v11, so call super with the exact same arguments.
init(AttributeSet attrs, int defStyleAttr)108     private void init(AttributeSet attrs, int defStyleAttr) {
109         registerMixin(HeaderMixin.class, new ColoredHeaderMixin(this, attrs, defStyleAttr));
110         registerMixin(IconMixin.class, new IconMixin(this, attrs, defStyleAttr));
111         registerMixin(ProgressBarMixin.class, new ProgressBarMixin(this));
112         registerMixin(ButtonFooterMixin.class, new ButtonFooterMixin(this));
113         final RequireScrollMixin requireScrollMixin = new RequireScrollMixin(this);
114         registerMixin(RequireScrollMixin.class, requireScrollMixin);
115 
116         final ScrollView scrollView = getScrollView();
117         if (scrollView != null) {
118             requireScrollMixin.setScrollHandlingDelegate(
119                     new ScrollViewScrollHandlingDelegate(requireScrollMixin, scrollView));
120         }
121 
122         TypedArray a = getContext().obtainStyledAttributes(attrs,
123                 R.styleable.SuwGlifLayout, defStyleAttr, 0);
124 
125         ColorStateList primaryColor =
126                 a.getColorStateList(R.styleable.SuwGlifLayout_suwColorPrimary);
127         if (primaryColor != null) {
128             setPrimaryColor(primaryColor);
129         }
130 
131         ColorStateList backgroundColor =
132                 a.getColorStateList(R.styleable.SuwGlifLayout_suwBackgroundBaseColor);
133         setBackgroundBaseColor(backgroundColor);
134 
135         boolean backgroundPatterned =
136                 a.getBoolean(R.styleable.SuwGlifLayout_suwBackgroundPatterned, true);
137         setBackgroundPatterned(backgroundPatterned);
138 
139         final int footer = a.getResourceId(R.styleable.SuwGlifLayout_suwFooter, 0);
140         if (footer != 0) {
141             inflateFooter(footer);
142         }
143 
144         final int stickyHeader = a.getResourceId(R.styleable.SuwGlifLayout_suwStickyHeader, 0);
145         if (stickyHeader != 0) {
146             inflateStickyHeader(stickyHeader);
147         }
148 
149         mLayoutFullscreen = a.getBoolean(R.styleable.SuwGlifLayout_suwLayoutFullscreen, true);
150 
151         a.recycle();
152 
153         if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && mLayoutFullscreen) {
154             setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
155         }
156     }
157 
158     @Override
onInflateTemplate(LayoutInflater inflater, @LayoutRes int template)159     protected View onInflateTemplate(LayoutInflater inflater, @LayoutRes int template) {
160         if (template == 0) {
161             template = R.layout.suw_glif_template;
162         }
163         return inflateTemplate(inflater, R.style.SuwThemeGlif_Light, template);
164     }
165 
166     @Override
findContainer(int containerId)167     protected ViewGroup findContainer(int containerId) {
168         if (containerId == 0) {
169             containerId = R.id.suw_layout_content;
170         }
171         return super.findContainer(containerId);
172     }
173 
174     /**
175      * Sets the footer of the layout, which is at the bottom of the content area outside the
176      * scrolling container. The footer can only be inflated once per instance of this layout.
177      *
178      * @param footer The layout to be inflated as footer.
179      * @return The root of the inflated footer view.
180      */
inflateFooter(@ayoutRes int footer)181     public View inflateFooter(@LayoutRes int footer) {
182         ViewStub footerStub = findManagedViewById(R.id.suw_layout_footer);
183         footerStub.setLayoutResource(footer);
184         return footerStub.inflate();
185     }
186 
187     /**
188      * Sets the sticky header (i.e. header that doesn't scroll) of the layout, which is at the top
189      * of the content area outside of the scrolling container. The header can only be inflated once
190      * per instance of this layout.
191      *
192      * @param header The layout to be inflated as the header.
193      * @return The root of the inflated header view.
194      */
inflateStickyHeader(@ayoutRes int header)195     public View inflateStickyHeader(@LayoutRes int header) {
196         ViewStub stickyHeaderStub = findManagedViewById(R.id.suw_layout_sticky_header);
197         stickyHeaderStub.setLayoutResource(header);
198         return stickyHeaderStub.inflate();
199     }
200 
getScrollView()201     public ScrollView getScrollView() {
202         final View view = findManagedViewById(R.id.suw_scroll_view);
203         return view instanceof ScrollView ? (ScrollView) view : null;
204     }
205 
getHeaderTextView()206     public TextView getHeaderTextView() {
207         return getMixin(HeaderMixin.class).getTextView();
208     }
209 
setHeaderText(int title)210     public void setHeaderText(int title) {
211         getMixin(HeaderMixin.class).setText(title);
212     }
213 
setHeaderText(CharSequence title)214     public void setHeaderText(CharSequence title) {
215         getMixin(HeaderMixin.class).setText(title);
216     }
217 
getHeaderText()218     public CharSequence getHeaderText() {
219         return getMixin(HeaderMixin.class).getText();
220     }
221 
setHeaderColor(ColorStateList color)222     public void setHeaderColor(ColorStateList color) {
223         final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class);
224         mixin.setColor(color);
225     }
226 
getHeaderColor()227     public ColorStateList getHeaderColor() {
228         final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class);
229         return mixin.getColor();
230     }
231 
setIcon(Drawable icon)232     public void setIcon(Drawable icon) {
233         getMixin(IconMixin.class).setIcon(icon);
234     }
235 
getIcon()236     public Drawable getIcon() {
237         return getMixin(IconMixin.class).getIcon();
238     }
239 
240     /**
241      * Sets the primary color of this layout, which will be used to determine the color of the
242      * progress bar and the background pattern.
243      */
setPrimaryColor(@onNull ColorStateList color)244     public void setPrimaryColor(@NonNull ColorStateList color) {
245         mPrimaryColor = color;
246         updateBackground();
247         getMixin(ProgressBarMixin.class).setColor(color);
248     }
249 
getPrimaryColor()250     public ColorStateList getPrimaryColor() {
251         return mPrimaryColor;
252     }
253 
254     /**
255      * Sets the base color of the background view, which is the status bar for phones and the full-
256      * screen background for tablets. If {@link #isBackgroundPatterned()} is true, the pattern will
257      * be drawn with this color.
258      *
259      * @param color The color to use as the base color of the background. If {@code null},
260      *              {@link #getPrimaryColor()} will be used.
261      */
setBackgroundBaseColor(@ullable ColorStateList color)262     public void setBackgroundBaseColor(@Nullable ColorStateList color) {
263         mBackgroundBaseColor = color;
264         updateBackground();
265     }
266 
267     /**
268      * @return The base color of the background. {@code null} indicates the background will be drawn
269      *         with {@link #getPrimaryColor()}.
270      */
271     @Nullable
getBackgroundBaseColor()272     public ColorStateList getBackgroundBaseColor() {
273         return mBackgroundBaseColor;
274     }
275 
276     /**
277      * Sets whether the background should be {@link GlifPatternDrawable}. If {@code false}, the
278      * background will be a solid color.
279      */
setBackgroundPatterned(boolean patterned)280     public void setBackgroundPatterned(boolean patterned) {
281         mBackgroundPatterned = patterned;
282         updateBackground();
283     }
284 
285     /**
286      * @return True if this view uses {@link GlifPatternDrawable} as background.
287      */
isBackgroundPatterned()288     public boolean isBackgroundPatterned() {
289         return mBackgroundPatterned;
290     }
291 
updateBackground()292     private void updateBackground() {
293         final View patternBg = findManagedViewById(R.id.suw_pattern_bg);
294         if (patternBg != null) {
295             int backgroundColor = 0;
296             if (mBackgroundBaseColor != null) {
297                 backgroundColor = mBackgroundBaseColor.getDefaultColor();
298             } else if (mPrimaryColor != null) {
299                 backgroundColor = mPrimaryColor.getDefaultColor();
300             }
301             Drawable background = mBackgroundPatterned
302                     ? new GlifPatternDrawable(backgroundColor)
303                     : new ColorDrawable(backgroundColor);
304             if (patternBg instanceof StatusBarBackgroundLayout) {
305                 ((StatusBarBackgroundLayout) patternBg).setStatusBarBackground(background);
306             } else {
307                 patternBg.setBackgroundDrawable(background);
308             }
309         }
310     }
311 
isProgressBarShown()312     public boolean isProgressBarShown() {
313         return getMixin(ProgressBarMixin.class).isShown();
314     }
315 
setProgressBarShown(boolean shown)316     public void setProgressBarShown(boolean shown) {
317         getMixin(ProgressBarMixin.class).setShown(shown);
318     }
319 
peekProgressBar()320     public ProgressBar peekProgressBar() {
321         return getMixin(ProgressBarMixin.class).peekProgressBar();
322     }
323 }
324