diff options
Diffstat (limited to 'library/main')
10 files changed, 585 insertions, 173 deletions
diff --git a/library/main/res/values/attrs.xml b/library/main/res/values/attrs.xml index 1fedecc..984b6cd 100644 --- a/library/main/res/values/attrs.xml +++ b/library/main/res/values/attrs.xml @@ -35,7 +35,6 @@ <!-- Custom view attributes --> <attr name="suwColorPrimary" format="color" /> <attr name="suwHeader" format="reference" /> - <attr name="suwHeaderText" format="string" localization="suggested" /> <attr name="suwDividerInset" format="dimension|reference" /> <attr name="suwItemDescriptionStyle" format="reference" /> @@ -52,10 +51,7 @@ </declare-styleable> <declare-styleable name="SuwGlifLayout"> - <attr name="android:icon" /> <attr name="suwColorPrimary" /> - <attr name="suwHeaderColor" format="reference|color" /> - <attr name="suwHeaderText" /> </declare-styleable> <declare-styleable name="SuwGlifListLayout"> @@ -75,7 +71,6 @@ <declare-styleable name="SuwSetupWizardLayout"> <attr name="suwBackground" format="color|reference" /> <attr name="suwBackgroundTile" format="color|reference" /> - <attr name="suwHeaderText" /> <attr name="suwDecorPaddingTop" format="dimension|reference" /> <attr name="suwIllustration" format="color|reference" /> <attr name="suwIllustrationAspectRatio" format="float|reference" /> @@ -122,4 +117,16 @@ <attr name="android:theme" /> </declare-styleable> + <declare-styleable name="SuwHeaderMixin"> + <attr name="suwHeaderText" format="string" localization="suggested" /> + </declare-styleable> + + <declare-styleable name="SuwColoredHeaderMixin"> + <attr name="suwHeaderColor" format="reference|color" /> + </declare-styleable> + + <declare-styleable name="SuwIconMixin"> + <attr name="android:icon" /> + </declare-styleable> + </resources> diff --git a/library/main/src/com/android/setupwizardlib/GlifLayout.java b/library/main/src/com/android/setupwizardlib/GlifLayout.java index 13d35fe..a6a852c 100644 --- a/library/main/src/com/android/setupwizardlib/GlifLayout.java +++ b/library/main/src/com/android/setupwizardlib/GlifLayout.java @@ -29,12 +29,14 @@ import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewStub; -import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.ScrollView; import android.widget.TextView; +import com.android.setupwizardlib.template.ColoredHeaderMixin; +import com.android.setupwizardlib.template.HeaderMixin; +import com.android.setupwizardlib.template.IconMixin; +import com.android.setupwizardlib.template.ProgressBarMixin; import com.android.setupwizardlib.view.StatusBarBackgroundLayout; /** @@ -88,29 +90,13 @@ public class GlifLayout extends TemplateLayout { // All the constructors delegate to this init method. The 3-argument constructor is not // available in LinearLayout before v11, so call super with the exact same arguments. private void init(AttributeSet attrs, int defStyleAttr) { + registerMixin(HeaderMixin.class, new ColoredHeaderMixin(this, attrs, defStyleAttr)); + registerMixin(IconMixin.class, new IconMixin(this, attrs, defStyleAttr)); + registerMixin(ProgressBarMixin.class, new ProgressBarMixin(this)); + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.SuwGlifLayout, defStyleAttr, 0); - final Drawable icon = a.getDrawable(R.styleable.SuwGlifLayout_android_icon); - if (icon != null) { - setIcon(icon); - } - - // Set the header color - final ColorStateList headerColor = - a.getColorStateList(R.styleable.SuwGlifLayout_suwHeaderColor); - if (headerColor != null) { - setHeaderColor(headerColor); - } - - - // Set the header text - final CharSequence headerText = - a.getText(R.styleable.SuwGlifLayout_suwHeaderText); - if (headerText != null) { - setHeaderText(headerText); - } - ColorStateList primaryColor = a.getColorStateList(R.styleable.SuwGlifLayout_suwColorPrimary); @@ -149,72 +135,49 @@ public class GlifLayout extends TemplateLayout { return super.findContainer(containerId); } - /** - * Same as {@link android.view.View#findViewById(int)}, but may include views that are managed - * by this view but not currently added to the view hierarchy. e.g. recycler view or list view - * headers that are not currently shown. - */ - protected View findManagedViewById(int id) { - return findViewById(id); - } - public ScrollView getScrollView() { final View view = findManagedViewById(R.id.suw_scroll_view); return view instanceof ScrollView ? (ScrollView) view : null; } public TextView getHeaderTextView() { - return (TextView) findManagedViewById(R.id.suw_layout_title); + return getMixin(HeaderMixin.class).getTextView(); } public void setHeaderText(int title) { - setHeaderText(getContext().getResources().getText(title)); + getMixin(HeaderMixin.class).setText(title); } public void setHeaderText(CharSequence title) { - final TextView titleView = getHeaderTextView(); - if (titleView != null) { - titleView.setText(title); - } + getMixin(HeaderMixin.class).setText(title); } public CharSequence getHeaderText() { - final TextView titleView = getHeaderTextView(); - return titleView != null ? titleView.getText() : null; + return getMixin(HeaderMixin.class).getText(); } public void setHeaderColor(ColorStateList color) { - final TextView titleView = getHeaderTextView(); - if (titleView != null) { - titleView.setTextColor(color); - } + final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class); + mixin.setColor(color); } public ColorStateList getHeaderColor() { - final TextView titleView = getHeaderTextView(); - return titleView != null ? titleView.getTextColors() : null; + final ColoredHeaderMixin mixin = (ColoredHeaderMixin) getMixin(HeaderMixin.class); + return mixin.getColor(); } public void setIcon(Drawable icon) { - final ImageView iconView = getIconView(); - if (iconView != null) { - iconView.setImageDrawable(icon); - } + getMixin(IconMixin.class).setIcon(icon); } public Drawable getIcon() { - final ImageView iconView = getIconView(); - return iconView != null ? iconView.getDrawable() : null; - } - - protected ImageView getIconView() { - return (ImageView) findManagedViewById(R.id.suw_layout_icon); + return getMixin(IconMixin.class).getIcon(); } public void setPrimaryColor(ColorStateList color) { mPrimaryColor = color; setGlifPatternColor(color); - setProgressBarColor(color); + getMixin(ProgressBarMixin.class).setColor(color); } public ColorStateList getPrimaryColor() { @@ -239,64 +202,14 @@ public class GlifLayout extends TemplateLayout { } public boolean isProgressBarShown() { - final View progressBar = findManagedViewById(R.id.suw_layout_progress); - return progressBar != null && progressBar.getVisibility() == View.VISIBLE; + return getMixin(ProgressBarMixin.class).isShown(); } public void setProgressBarShown(boolean shown) { - if (shown) { - View progressBar = getProgressBar(); - if (progressBar != null) { - progressBar.setVisibility(View.VISIBLE); - } - } else { - View progressBar = peekProgressBar(); - if (progressBar != null) { - progressBar.setVisibility(View.GONE); - } - } + getMixin(ProgressBarMixin.class).setShown(shown); } - /** - * Gets the progress bar in the layout. If the progress bar has not been used before, it will be - * installed (i.e. inflated from its view stub). - * - * @return The progress bar of this layout. May be null only if the template used doesn't have a - * progress bar built-in. - */ - private ProgressBar getProgressBar() { - final View progressBar = peekProgressBar(); - if (progressBar == null) { - final ViewStub progressBarStub = - (ViewStub) findManagedViewById(R.id.suw_layout_progress_stub); - if (progressBarStub != null) { - progressBarStub.inflate(); - } - setProgressBarColor(mPrimaryColor); - } - return peekProgressBar(); - } - - /** - * Gets the progress bar in the layout only if it has been installed. - * {@link #setProgressBarShown(boolean)} should be called before this to ensure the progress bar - * is set up correctly. - * - * @return The progress bar of this layout, or null if the progress bar is not installed. The - * null case can happen either if {@link #setProgressBarShown(boolean)} with true was - * not called before this, or if the template does not contain a progress bar. - */ public ProgressBar peekProgressBar() { - return (ProgressBar) findManagedViewById(R.id.suw_layout_progress); - } - - private void setProgressBarColor(ColorStateList color) { - if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { - final ProgressBar bar = peekProgressBar(); - if (bar != null) { - bar.setIndeterminateTintList(color); - bar.setProgressBackgroundTintList(color); - } - } + return getMixin(ProgressBarMixin.class).peekProgressBar(); } } diff --git a/library/main/src/com/android/setupwizardlib/SetupWizardLayout.java b/library/main/src/com/android/setupwizardlib/SetupWizardLayout.java index 79d9222..c30a12d 100644 --- a/library/main/src/com/android/setupwizardlib/SetupWizardLayout.java +++ b/library/main/src/com/android/setupwizardlib/SetupWizardLayout.java @@ -37,11 +37,12 @@ import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewStub; -import android.widget.ProgressBar; import android.widget.ScrollView; import android.widget.TextView; +import com.android.setupwizardlib.template.HeaderMixin; +import com.android.setupwizardlib.template.NavigationBarMixin; +import com.android.setupwizardlib.template.ProgressBarMixin; import com.android.setupwizardlib.util.RequireScrollHelper; import com.android.setupwizardlib.view.BottomScrollView; import com.android.setupwizardlib.view.Illustration; @@ -51,8 +52,6 @@ public class SetupWizardLayout extends TemplateLayout { private static final String TAG = "SetupWizardLayout"; - private ColorStateList mProgressBarColor; - public SetupWizardLayout(Context context) { super(context, 0, 0); init(null, R.attr.suwLayoutTheme); @@ -81,6 +80,10 @@ public class SetupWizardLayout extends TemplateLayout { // All the constructors delegate to this init method. The 3-argument constructor is not // available in LinearLayout before v11, so call super with the exact same arguments. private void init(AttributeSet attrs, int defStyleAttr) { + registerMixin(HeaderMixin.class, new HeaderMixin(this, attrs, defStyleAttr)); + registerMixin(ProgressBarMixin.class, new ProgressBarMixin(this)); + registerMixin(NavigationBarMixin.class, new NavigationBarMixin(this)); + final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.SuwSetupWizardLayout, defStyleAttr, 0); @@ -132,13 +135,6 @@ public class SetupWizardLayout extends TemplateLayout { } setIllustrationAspectRatio(illustrationAspectRatio); - // Set the header text - final CharSequence headerText = - a.getText(R.styleable.SuwSetupWizardLayout_suwHeaderText); - if (headerText != null) { - setHeaderText(headerText); - } - a.recycle(); } @@ -192,8 +188,7 @@ public class SetupWizardLayout extends TemplateLayout { } public NavigationBar getNavigationBar() { - final View view = findManagedViewById(R.id.suw_layout_navigation_bar); - return view instanceof NavigationBar ? (NavigationBar) view : null; + return getMixin(NavigationBarMixin.class).getNavigationBar(); } public ScrollView getScrollView() { @@ -213,26 +208,19 @@ public class SetupWizardLayout extends TemplateLayout { } public void setHeaderText(int title) { - final TextView titleView = getHeaderTextView(); - if (titleView != null) { - titleView.setText(title); - } + getMixin(HeaderMixin.class).setText(title); } public void setHeaderText(CharSequence title) { - final TextView titleView = getHeaderTextView(); - if (titleView != null) { - titleView.setText(title); - } + getMixin(HeaderMixin.class).setText(title); } public CharSequence getHeaderText() { - final TextView titleView = getHeaderTextView(); - return titleView != null ? titleView.getText() : null; + return getMixin(HeaderMixin.class).getText(); } public TextView getHeaderTextView() { - return (TextView) findManagedViewById(R.id.suw_layout_title); + return getMixin(HeaderMixin.class).getTextView(); } /** @@ -375,18 +363,8 @@ public class SetupWizardLayout extends TemplateLayout { } } - /** - * Same as {@link android.view.View#findViewById(int)}, but may include views that are managed - * by this view but not currently added to the view hierarchy. e.g. recycler view or list view - * headers that are not currently shown. - */ - protected View findManagedViewById(int id) { - return findViewById(id); - } - public boolean isProgressBarShown() { - final View progressBar = findManagedViewById(R.id.suw_layout_progress); - return progressBar != null && progressBar.getVisibility() == View.VISIBLE; + return getMixin(ProgressBarMixin.class).isShown(); } /** @@ -395,19 +373,7 @@ public class SetupWizardLayout extends TemplateLayout { * view hierarchy until the first time this is set to {@code true}. */ public void setProgressBarShown(boolean shown) { - final View progressBar = findManagedViewById(R.id.suw_layout_progress); - if (progressBar != null) { - progressBar.setVisibility(shown ? View.VISIBLE : View.GONE); - } else if (shown) { - final ViewStub progressBarStub = - (ViewStub) findManagedViewById(R.id.suw_layout_progress_stub); - if (progressBarStub != null) { - progressBarStub.inflate(); - } - if (mProgressBarColor != null) { - setProgressBarColor(mProgressBarColor); - } - } + getMixin(ProgressBarMixin.class).setShown(shown); } /** @@ -427,20 +393,11 @@ public class SetupWizardLayout extends TemplateLayout { } public void setProgressBarColor(ColorStateList color) { - mProgressBarColor = color; - if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { - // Suppress lint error caused by - // https://code.google.com/p/android/issues/detail?id=183136 - // noinspection AndroidLintWrongViewCast - final ProgressBar bar = (ProgressBar) findViewById(R.id.suw_layout_progress); - if (bar != null) { - bar.setIndeterminateTintList(color); - } - } + getMixin(ProgressBarMixin.class).setColor(color); } public ColorStateList getProgressBarColor() { - return mProgressBarColor; + return getMixin(ProgressBarMixin.class).getColor(); } /* Misc */ diff --git a/library/main/src/com/android/setupwizardlib/TemplateLayout.java b/library/main/src/com/android/setupwizardlib/TemplateLayout.java index 90666d2..3eae3af 100644 --- a/library/main/src/com/android/setupwizardlib/TemplateLayout.java +++ b/library/main/src/com/android/setupwizardlib/TemplateLayout.java @@ -28,6 +28,11 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.FrameLayout; +import com.android.setupwizardlib.template.Mixin; + +import java.util.HashMap; +import java.util.Map; + /** * A generic template class that inflates a template, provided in the constructor or in * {@code android:layout} through XML, and adds its children to a "container" in the template. When @@ -42,6 +47,8 @@ public class TemplateLayout extends FrameLayout { */ private ViewGroup mContainer; + private Map<Class<? extends Mixin>, Mixin> mMixins = new HashMap<>(); + public TemplateLayout(Context context, int template, int containerId) { super(context); init(template, containerId, null, R.attr.suwLayoutTheme); @@ -74,6 +81,46 @@ public class TemplateLayout extends FrameLayout { a.recycle(); } + /** + * Registers a mixin with a given class. This method should be called in the constructor. + * + * @param cls The class to register the mixin. In most cases, {@code cls} is the same as + * {@code mixin.getClass()}, but {@code cls} can also be a super class of that. In + * the latter case the the mixin must be retrieved using {@code cls} in + * {@link #getMixin(Class)}, not the subclass. + * @param mixin The mixin to be registered. + * @param <M> The class of the mixin to register. This is the same as {@code cls} + */ + protected <M extends Mixin> void registerMixin(Class<M> cls, M mixin) { + mMixins.put(cls, mixin); + } + + /** + * Same as {@link android.view.View#findViewById(int)}, but may include views that are managed + * by this view but not currently added to the view hierarchy. e.g. recycler view or list view + * headers that are not currently shown. + */ + public View findManagedViewById(int id) { + return findViewById(id); + } + + /** + * Get a {@link Mixin} from this template registered earlier in + * {@link #registerMixin(Class, Mixin)}. + * + * @param cls The class marker of Mixin being requested. The actual Mixin returned may be a + * subclass of this marker. Note that this must be the same class as registered in + * {@link #registerMixin(Class, Mixin)}, which is not necessarily the + * same as the concrete class of the instance returned by this method. + * @param <M> The type of the class marker. + * @return The mixin marked by {@code cls}, or null if the template does not have a matching + * mixin. + */ + @SuppressWarnings("unchecked") + public <M extends Mixin> M getMixin(Class<M> cls) { + return (M) mMixins.get(cls); + } + @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { mContainer.addView(child, index, params); diff --git a/library/main/src/com/android/setupwizardlib/template/ColoredHeaderMixin.java b/library/main/src/com/android/setupwizardlib/template/ColoredHeaderMixin.java new file mode 100644 index 0000000..ccc5aad --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/template/ColoredHeaderMixin.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.setupwizardlib.template; + +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.android.setupwizardlib.R; +import com.android.setupwizardlib.TemplateLayout; + +/** + * A {@link Mixin} displaying a header text that can be set to different colors. This Mixin is + * registered to the tempalte using HeaderMixin.class, and can be retrieved using: + * {@code (ColoredHeaderMixin) templateLayout.getMixin(HeaderMixin.class}. + */ +public class ColoredHeaderMixin extends HeaderMixin { + + /** + * {@inheritDoc} + */ + public ColoredHeaderMixin(TemplateLayout layout, AttributeSet attrs, int defStyleAttr) { + super(layout, attrs, defStyleAttr); + + final TypedArray a = layout.getContext().obtainStyledAttributes( + attrs, R.styleable.SuwColoredHeaderMixin, defStyleAttr, 0); + + // Set the header color + final ColorStateList headerColor = + a.getColorStateList(R.styleable.SuwColoredHeaderMixin_suwHeaderColor); + if (headerColor != null) { + setColor(headerColor); + } + + a.recycle(); + } + + /** + * Sets the color of the header text. This can also be set via XML using + * {@code app:suwHeaderColor}. + * + * @param color The text color of the header. + */ + public void setColor(ColorStateList color) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setTextColor(color); + } + } + + /** + * @return The current text color of the header. + */ + public ColorStateList getColor() { + final TextView titleView = getTextView(); + return titleView != null ? titleView.getTextColors() : null; + } +} diff --git a/library/main/src/com/android/setupwizardlib/template/HeaderMixin.java b/library/main/src/com/android/setupwizardlib/template/HeaderMixin.java new file mode 100644 index 0000000..bd3f210 --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/template/HeaderMixin.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.setupwizardlib.template; + +import android.content.res.TypedArray; +import android.support.annotation.AttrRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.android.setupwizardlib.R; +import com.android.setupwizardlib.TemplateLayout; + +/** + * A {@link Mixin} for setting and getting the header text. + */ +public class HeaderMixin implements Mixin { + + private TemplateLayout mTemplateLayout; + + /** + * @param layout The layout this Mixin belongs to. + * @param attrs XML attributes given to the layout. + * @param defStyleAttr The default style attribute as given to the constructor of the layout. + */ + public HeaderMixin(@NonNull TemplateLayout layout, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr) { + mTemplateLayout = layout; + + final TypedArray a = layout.getContext().obtainStyledAttributes( + attrs, R.styleable.SuwHeaderMixin, defStyleAttr, 0); + + // Set the header text + final CharSequence headerText = a.getText(R.styleable.SuwHeaderMixin_suwHeaderText); + if (headerText != null) { + setText(headerText); + } + + a.recycle(); + } + + /** + * @return The TextView displaying the header. + */ + public TextView getTextView() { + return (TextView) mTemplateLayout.findManagedViewById(R.id.suw_layout_title); + } + + /** + * Sets the header text. This can also be set via the XML attribute {@code app:suwHeaderText}. + * + * @param title The resource ID of the text to be set as header. + */ + public void setText(int title) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setText(title); + } + } + + /** + * Sets the header text. This can also be set via the XML attribute {@code app:suwHeaderText}. + * + * @param title The text to be set as header. + */ + public void setText(CharSequence title) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setText(title); + } + } + + /** + * @return The current header text. + */ + public CharSequence getText() { + final TextView titleView = getTextView(); + return titleView != null ? titleView.getText() : null; + } +} diff --git a/library/main/src/com/android/setupwizardlib/template/IconMixin.java b/library/main/src/com/android/setupwizardlib/template/IconMixin.java new file mode 100644 index 0000000..46c23f0 --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/template/IconMixin.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.setupwizardlib.template; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.android.setupwizardlib.R; +import com.android.setupwizardlib.TemplateLayout; + +/** + * A {@link Mixin} for setting an icon on the template layout. + */ +public class IconMixin implements Mixin { + + private TemplateLayout mTemplateLayout; + + /** + * @param layout The template layout that this Mixin is a part of. + * @param attrs XML attributes given to the layout. + * @param defStyleAttr The default style attribute as given to the constructor of the layout. + */ + public IconMixin(TemplateLayout layout, AttributeSet attrs, int defStyleAttr) { + mTemplateLayout = layout; + final Context context = layout.getContext(); + + final TypedArray a = + context.obtainStyledAttributes(attrs, R.styleable.SuwIconMixin, defStyleAttr, 0); + + final Drawable icon = a.getDrawable(R.styleable.SuwIconMixin_android_icon); + if (icon != null) { + setIcon(icon); + } + + a.recycle(); + } + + /** + * Sets the icon on this layout. The icon can also be set in XML using {@code android:icon}. + * + * @param icon A drawable icon. + */ + public void setIcon(Drawable icon) { + final ImageView iconView = getView(); + if (iconView != null) { + iconView.setImageDrawable(icon); + } + } + + /** + * @return The icon previously set in {@link #setIcon(Drawable)} or {@code android:icon} + */ + public Drawable getIcon() { + final ImageView iconView = getView(); + return iconView != null ? iconView.getDrawable() : null; + } + + /** + * @return The ImageView responsible for displaying the icon. + */ + protected ImageView getView() { + return (ImageView) mTemplateLayout.findManagedViewById(R.id.suw_layout_icon); + } +} diff --git a/library/main/src/com/android/setupwizardlib/template/Mixin.java b/library/main/src/com/android/setupwizardlib/template/Mixin.java new file mode 100644 index 0000000..285ea31 --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/template/Mixin.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.setupwizardlib.template; + +/** + * Marker interface to indicate Mixin classes. + * + * @see TemplateLayout#registerMixin(Class, Mixin) + * @see TemplateLayout#getMixin(Class) + */ +public interface Mixin { +} diff --git a/library/main/src/com/android/setupwizardlib/template/NavigationBarMixin.java b/library/main/src/com/android/setupwizardlib/template/NavigationBarMixin.java new file mode 100644 index 0000000..df35017 --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/template/NavigationBarMixin.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.setupwizardlib.template; + +import android.view.View; + +import com.android.setupwizardlib.R; +import com.android.setupwizardlib.TemplateLayout; +import com.android.setupwizardlib.view.NavigationBar; +import com.android.setupwizardlib.view.NavigationBar.NavigationBarListener; + +/** + * A {@link Mixin} for interacting with a {@link NavigationBar}. + */ +public class NavigationBarMixin implements Mixin { + + private TemplateLayout mTemplateLayout; + + /** + * @param layout The layout this mixin belongs to. + */ + public NavigationBarMixin(TemplateLayout layout) { + mTemplateLayout = layout; + } + + /** + * @return The navigation bar instance in the layout, or null if the layout does not have a + * navigation bar. + */ + public NavigationBar getNavigationBar() { + final View view = mTemplateLayout.findManagedViewById(R.id.suw_layout_navigation_bar); + return view instanceof NavigationBar ? (NavigationBar) view : null; + } + + /** + * Sets the label of the next button. + * + * @param text Label of the next button. + */ + public void setNextButtonText(int text) { + getNavigationBar().getNextButton().setText(text); + } + + /** + * Sets the label of the next button. + * + * @param text Label of the next button. + */ + public void setNextButtonText(CharSequence text) { + getNavigationBar().getNextButton().setText(text); + } + + /** + * @return The current label of the next button. + */ + public CharSequence getNextButtonText() { + return getNavigationBar().getNextButton().getText(); + } + + /** + * Sets the listener to handle back and next button clicks in the navigation bar. + * + * @see NavigationBar#setNavigationBarListener(NavigationBarListener) + * @see NavigationBarListener + */ + public void setNavigationBarListener(NavigationBarListener listener) { + getNavigationBar().setNavigationBarListener(listener); + } +} diff --git a/library/main/src/com/android/setupwizardlib/template/ProgressBarMixin.java b/library/main/src/com/android/setupwizardlib/template/ProgressBarMixin.java new file mode 100644 index 0000000..d5c038e --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/template/ProgressBarMixin.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.setupwizardlib.template; + +import android.content.res.ColorStateList; +import android.os.Build; +import android.os.Build.VERSION_CODES; +import android.support.annotation.Nullable; +import android.view.View; +import android.view.ViewStub; +import android.widget.ProgressBar; + +import com.android.setupwizardlib.R; +import com.android.setupwizardlib.TemplateLayout; + +/** + * A {@link Mixin} for showing a progress bar. + */ +public class ProgressBarMixin implements Mixin { + + private TemplateLayout mTemplateLayout; + + @Nullable + private ColorStateList mColor; + + /** + * @param layout The layout this mixin belongs to. + */ + public ProgressBarMixin(TemplateLayout layout) { + mTemplateLayout = layout; + } + + /** + * @return True if the progress bar is currently shown. + */ + public boolean isShown() { + final View progressBar = mTemplateLayout.findManagedViewById(R.id.suw_layout_progress); + return progressBar != null && progressBar.getVisibility() == View.VISIBLE; + } + + /** + * Sets whether the progress bar is shown. If the progress bar has not been inflated from the + * stub, this method will inflate the progress bar. + * + * @param shown True to show the progress bar, false to hide it. + */ + public void setShown(boolean shown) { + if (shown) { + View progressBar = getProgressBar(); + if (progressBar != null) { + progressBar.setVisibility(View.VISIBLE); + } + } else { + View progressBar = peekProgressBar(); + if (progressBar != null) { + progressBar.setVisibility(View.GONE); + } + } + } + + /** + * Gets the progress bar in the layout. If the progress bar has not been used before, it will be + * installed (i.e. inflated from its view stub). + * + * @return The progress bar of this layout. May be null only if the template used doesn't have a + * progress bar built-in. + */ + private ProgressBar getProgressBar() { + final View progressBar = peekProgressBar(); + if (progressBar == null) { + final ViewStub progressBarStub = + (ViewStub) mTemplateLayout.findManagedViewById(R.id.suw_layout_progress_stub); + if (progressBarStub != null) { + progressBarStub.inflate(); + } + setColor(mColor); + } + return peekProgressBar(); + } + + /** + * Gets the progress bar in the layout only if it has been installed. + * {@link #setShown(boolean)} should be called before this to ensure the progress bar + * is set up correctly. + * + * @return The progress bar of this layout, or null if the progress bar is not installed. The + * null case can happen either if {@link #setShown(boolean)} with true was + * not called before this, or if the template does not contain a progress bar. + */ + public ProgressBar peekProgressBar() { + return (ProgressBar) mTemplateLayout.findManagedViewById(R.id.suw_layout_progress); + } + + /** + * Sets the color of the indeterminate progress bar. This method is a no-op on SDK < 21. + */ + public void setColor(@Nullable ColorStateList color) { + mColor = color; + if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + final ProgressBar bar = peekProgressBar(); + if (bar != null) { + bar.setIndeterminateTintList(color); + bar.setProgressBackgroundTintList(color); + } + } + } + + /** + * @return The color previously set in {@link #setColor(ColorStateList)}, or null if the color + * is not set. In case of null, the color of the progress bar will be inherited from the theme. + */ + @Nullable + public ColorStateList getColor() { + return mColor; + } +} |