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 * <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 * <!-- Content here --> 62 * 63 * </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 GlifLayout(Context context)80 public GlifLayout(Context context) { 81 this(context, 0, 0); 82 } 83 GlifLayout(Context context, int template)84 public GlifLayout(Context context, int template) { 85 this(context, template, 0); 86 } 87 GlifLayout(Context context, int template, int containerId)88 public GlifLayout(Context context, int template, int containerId) { 89 super(context, template, containerId); 90 init(null, R.attr.suwLayoutTheme); 91 } 92 GlifLayout(Context context, AttributeSet attrs)93 public GlifLayout(Context context, AttributeSet attrs) { 94 super(context, attrs); 95 init(attrs, R.attr.suwLayoutTheme); 96 } 97 98 @TargetApi(VERSION_CODES.HONEYCOMB) GlifLayout(Context context, AttributeSet attrs, int defStyleAttr)99 public GlifLayout(Context context, AttributeSet attrs, int defStyleAttr) { 100 super(context, attrs, defStyleAttr); 101 init(attrs, defStyleAttr); 102 } 103 104 // All the constructors delegate to this init method. The 3-argument constructor is not 105 // available in LinearLayout before v11, so call super with the exact same arguments. init(AttributeSet attrs, int defStyleAttr)106 private void init(AttributeSet attrs, int defStyleAttr) { 107 registerMixin(HeaderMixin.class, new ColoredHeaderMixin(this, attrs, defStyleAttr)); 108 registerMixin(IconMixin.class, new IconMixin(this, attrs, defStyleAttr)); 109 registerMixin(ProgressBarMixin.class, new ProgressBarMixin(this)); 110 registerMixin(ButtonFooterMixin.class, new ButtonFooterMixin(this)); 111 final RequireScrollMixin requireScrollMixin = new RequireScrollMixin(this); 112 registerMixin(RequireScrollMixin.class, requireScrollMixin); 113 114 final ScrollView scrollView = getScrollView(); 115 if (scrollView != null) { 116 requireScrollMixin.setScrollHandlingDelegate( 117 new ScrollViewScrollHandlingDelegate(requireScrollMixin, scrollView)); 118 } 119 120 TypedArray a = getContext().obtainStyledAttributes(attrs, 121 R.styleable.SuwGlifLayout, defStyleAttr, 0); 122 123 ColorStateList primaryColor = 124 a.getColorStateList(R.styleable.SuwGlifLayout_suwColorPrimary); 125 if (primaryColor != null) { 126 setPrimaryColor(primaryColor); 127 } 128 129 ColorStateList backgroundColor = 130 a.getColorStateList(R.styleable.SuwGlifLayout_suwBackgroundBaseColor); 131 setBackgroundBaseColor(backgroundColor); 132 133 boolean backgroundPatterned = 134 a.getBoolean(R.styleable.SuwGlifLayout_suwBackgroundPatterned, true); 135 setBackgroundPatterned(backgroundPatterned); 136 137 final int footer = a.getResourceId(R.styleable.SuwGlifLayout_suwFooter, 0); 138 if (footer != 0) { 139 inflateFooter(footer); 140 } 141 142 a.recycle(); 143 } 144 145 @Override onInflateTemplate(LayoutInflater inflater, @LayoutRes int template)146 protected View onInflateTemplate(LayoutInflater inflater, @LayoutRes int template) { 147 if (template == 0) { 148 template = R.layout.suw_glif_template; 149 } 150 return inflateTemplate(inflater, R.style.SuwThemeGlif_Light, template); 151 } 152 153 @Override findContainer(int containerId)154 protected ViewGroup findContainer(int containerId) { 155 if (containerId == 0) { 156 containerId = R.id.suw_layout_content; 157 } 158 return super.findContainer(containerId); 159 } 160 161 /** 162 * Sets the footer of the layout, which is at the bottom of the content area outside the 163 * scrolling container. The footer can only be inflated once per layout. 164 * 165 * @param footer The layout to be inflated as footer. 166 * @return The root of the inflated footer view. 167 */ inflateFooter(@ayoutRes int footer)168 public View inflateFooter(@LayoutRes int footer) { 169 ViewStub footerStub = (ViewStub) findManagedViewById(R.id.suw_layout_footer); 170 footerStub.setLayoutResource(footer); 171 return footerStub.inflate(); 172 } 173 getScrollView()174 public ScrollView getScrollView() { 175 final View view = findManagedViewById(R.id.suw_scroll_view); 176 return view instanceof ScrollView ? (ScrollView) view : null; 177 } 178 getHeaderTextView()179 public TextView getHeaderTextView() { 180 return getMixin(HeaderMixin.class).getTextView(); 181 } 182 setHeaderText(int title)183 public void setHeaderText(int title) { 184 getMixin(HeaderMixin.class).setText(title); 185 } 186 setHeaderText(CharSequence title)187 public void setHeaderText(CharSequence title) { 188 getMixin(HeaderMixin.class).setText(title); 189 } 190 getHeaderText()191 public CharSequence getHeaderText() { 192 return getMixin(HeaderMixin.class).getText(); 193 } 194 setHeaderColor(ColorStateList color)195 public void setHeaderColor(ColorStateList color) { 196 final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class); 197 mixin.setColor(color); 198 } 199 getHeaderColor()200 public ColorStateList getHeaderColor() { 201 final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class); 202 return mixin.getColor(); 203 } 204 setIcon(Drawable icon)205 public void setIcon(Drawable icon) { 206 getMixin(IconMixin.class).setIcon(icon); 207 } 208 getIcon()209 public Drawable getIcon() { 210 return getMixin(IconMixin.class).getIcon(); 211 } 212 213 /** 214 * Sets the primary color of this layout, which will be used to determine the color of the 215 * progress bar and the background pattern. 216 */ setPrimaryColor(@onNull ColorStateList color)217 public void setPrimaryColor(@NonNull ColorStateList color) { 218 mPrimaryColor = color; 219 updateBackground(); 220 getMixin(ProgressBarMixin.class).setColor(color); 221 } 222 getPrimaryColor()223 public ColorStateList getPrimaryColor() { 224 return mPrimaryColor; 225 } 226 227 /** 228 * Sets the base color of the background view, which is the status bar for phones and the full- 229 * screen background for tablets. If {@link #isBackgroundPatterned()} is true, the pattern will 230 * be drawn with this color. 231 * 232 * @param color The color to use as the base color of the background. If {@code null}, 233 * {@link #getPrimaryColor()} will be used. 234 */ setBackgroundBaseColor(@ullable ColorStateList color)235 public void setBackgroundBaseColor(@Nullable ColorStateList color) { 236 mBackgroundBaseColor = color; 237 updateBackground(); 238 } 239 240 /** 241 * @return The base color of the background. {@code null} indicates the background will be drawn 242 * with {@link #getPrimaryColor()}. 243 */ 244 @Nullable getBackgroundBaseColor()245 public ColorStateList getBackgroundBaseColor() { 246 return mBackgroundBaseColor; 247 } 248 249 /** 250 * Sets whether the background should be {@link GlifPatternDrawable}. If {@code false}, the 251 * background will be a solid color. 252 */ setBackgroundPatterned(boolean patterned)253 public void setBackgroundPatterned(boolean patterned) { 254 mBackgroundPatterned = patterned; 255 updateBackground(); 256 } 257 258 /** 259 * @return True if this view uses {@link GlifPatternDrawable} as background. 260 */ isBackgroundPatterned()261 public boolean isBackgroundPatterned() { 262 return mBackgroundPatterned; 263 } 264 updateBackground()265 private void updateBackground() { 266 final View patternBg = findManagedViewById(R.id.suw_pattern_bg); 267 if (patternBg != null) { 268 int backgroundColor = 0; 269 if (mBackgroundBaseColor != null) { 270 backgroundColor = mBackgroundBaseColor.getDefaultColor(); 271 } else if (mPrimaryColor != null) { 272 backgroundColor = mPrimaryColor.getDefaultColor(); 273 } 274 Drawable background = mBackgroundPatterned 275 ? new GlifPatternDrawable(backgroundColor) 276 : new ColorDrawable(backgroundColor); 277 if (patternBg instanceof StatusBarBackgroundLayout) { 278 ((StatusBarBackgroundLayout) patternBg).setStatusBarBackground(background); 279 } else { 280 patternBg.setBackgroundDrawable(background); 281 } 282 } 283 if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 284 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 285 } 286 } 287 isProgressBarShown()288 public boolean isProgressBarShown() { 289 return getMixin(ProgressBarMixin.class).isShown(); 290 } 291 setProgressBarShown(boolean shown)292 public void setProgressBarShown(boolean shown) { 293 getMixin(ProgressBarMixin.class).setShown(shown); 294 } 295 peekProgressBar()296 public ProgressBar peekProgressBar() { 297 return getMixin(ProgressBarMixin.class).peekProgressBar(); 298 } 299 } 300