Home | History | Annotate | Download | only in setupwizardlib
      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 
     82     public GlifLayout(Context context) {
     83         this(context, 0, 0);
     84     }
     85 
     86     public GlifLayout(Context context, int template) {
     87         this(context, template, 0);
     88     }
     89 
     90     public GlifLayout(Context context, int template, int containerId) {
     91         super(context, template, containerId);
     92         init(null, R.attr.suwLayoutTheme);
     93     }
     94 
     95     public GlifLayout(Context context, AttributeSet attrs) {
     96         super(context, attrs);
     97         init(attrs, R.attr.suwLayoutTheme);
     98     }
     99 
    100     @TargetApi(VERSION_CODES.HONEYCOMB)
    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.
    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
    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
    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      */
    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      */
    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 
    201     public ScrollView getScrollView() {
    202         final View view = findManagedViewById(R.id.suw_scroll_view);
    203         return view instanceof ScrollView ? (ScrollView) view : null;
    204     }
    205 
    206     public TextView getHeaderTextView() {
    207         return getMixin(HeaderMixin.class).getTextView();
    208     }
    209 
    210     public void setHeaderText(int title) {
    211         getMixin(HeaderMixin.class).setText(title);
    212     }
    213 
    214     public void setHeaderText(CharSequence title) {
    215         getMixin(HeaderMixin.class).setText(title);
    216     }
    217 
    218     public CharSequence getHeaderText() {
    219         return getMixin(HeaderMixin.class).getText();
    220     }
    221 
    222     public void setHeaderColor(ColorStateList color) {
    223         final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class);
    224         mixin.setColor(color);
    225     }
    226 
    227     public ColorStateList getHeaderColor() {
    228         final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class);
    229         return mixin.getColor();
    230     }
    231 
    232     public void setIcon(Drawable icon) {
    233         getMixin(IconMixin.class).setIcon(icon);
    234     }
    235 
    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      */
    244     public void setPrimaryColor(@NonNull ColorStateList color) {
    245         mPrimaryColor = color;
    246         updateBackground();
    247         getMixin(ProgressBarMixin.class).setColor(color);
    248     }
    249 
    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      */
    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
    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      */
    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      */
    288     public boolean isBackgroundPatterned() {
    289         return mBackgroundPatterned;
    290     }
    291 
    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 
    312     public boolean isProgressBarShown() {
    313         return getMixin(ProgressBarMixin.class).isShown();
    314     }
    315 
    316     public void setProgressBarShown(boolean shown) {
    317         getMixin(ProgressBarMixin.class).setShown(shown);
    318     }
    319 
    320     public ProgressBar peekProgressBar() {
    321         return getMixin(ProgressBarMixin.class).peekProgressBar();
    322     }
    323 }
    324