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.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 
     63     public GlifLayout(Context context) {
     64         this(context, 0, 0);
     65     }
     66 
     67     public GlifLayout(Context context, int template) {
     68         this(context, template, 0);
     69     }
     70 
     71     public GlifLayout(Context context, int template, int containerId) {
     72         super(context, template, containerId);
     73         init(null, R.attr.suwLayoutTheme);
     74     }
     75 
     76     public GlifLayout(Context context, AttributeSet attrs) {
     77         super(context, attrs);
     78         init(attrs, R.attr.suwLayoutTheme);
     79     }
     80 
     81     @TargetApi(VERSION_CODES.HONEYCOMB)
     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.
     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
    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
    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      */
    148     protected View findManagedViewById(int id) {
    149         return findViewById(id);
    150     }
    151 
    152     public ScrollView getScrollView() {
    153         final View view = findManagedViewById(R.id.suw_scroll_view);
    154         return view instanceof ScrollView ? (ScrollView) view : null;
    155     }
    156 
    157     public TextView getHeaderTextView() {
    158         return (TextView) findManagedViewById(R.id.suw_layout_title);
    159     }
    160 
    161     public void setHeaderText(int title) {
    162         setHeaderText(getContext().getResources().getText(title));
    163     }
    164 
    165     public void setHeaderText(CharSequence title) {
    166         final TextView titleView = getHeaderTextView();
    167         if (titleView != null) {
    168             titleView.setText(title);
    169         }
    170     }
    171 
    172     public CharSequence getHeaderText() {
    173         final TextView titleView = getHeaderTextView();
    174         return titleView != null ? titleView.getText() : null;
    175     }
    176 
    177     public void setHeaderColor(ColorStateList color) {
    178         final TextView titleView = getHeaderTextView();
    179         if (titleView != null) {
    180             titleView.setTextColor(color);
    181         }
    182     }
    183 
    184     public ColorStateList getHeaderColor() {
    185         final TextView titleView = getHeaderTextView();
    186         return titleView != null ? titleView.getTextColors() : null;
    187     }
    188 
    189     public void setIcon(Drawable icon) {
    190         final ImageView iconView = getIconView();
    191         if (iconView != null) {
    192             iconView.setImageDrawable(icon);
    193         }
    194     }
    195 
    196     public Drawable getIcon() {
    197         final ImageView iconView = getIconView();
    198         return iconView != null ? iconView.getDrawable() : null;
    199     }
    200 
    201     protected ImageView getIconView() {
    202         return (ImageView) findManagedViewById(R.id.suw_layout_icon);
    203     }
    204 
    205     public void setPrimaryColor(ColorStateList color) {
    206         mPrimaryColor = color;
    207         setGlifPatternColor(color);
    208         setProgressBarColor(color);
    209     }
    210 
    211     public ColorStateList getPrimaryColor() {
    212         return mPrimaryColor;
    213     }
    214 
    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 
    231     public boolean isProgressBarShown() {
    232         final View progressBar = findManagedViewById(R.id.suw_layout_progress);
    233         return progressBar != null && progressBar.getVisibility() == View.VISIBLE;
    234     }
    235 
    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      */
    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      */
    279     public ProgressBar peekProgressBar() {
    280         return (ProgressBar) findManagedViewById(R.id.suw_layout_progress);
    281     }
    282 
    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