1 /*
2  * Copyright (C) 2017 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.google.android.setupdesign.template;
18 
19 import android.content.Context;
20 import android.content.res.TypedArray;
21 import android.graphics.Color;
22 import android.graphics.drawable.Drawable;
23 import android.os.Build.VERSION;
24 import android.os.Build.VERSION_CODES;
25 import androidx.annotation.ColorInt;
26 import androidx.annotation.DrawableRes;
27 import androidx.annotation.Nullable;
28 import android.util.AttributeSet;
29 import android.view.View;
30 import android.view.ViewGroup.LayoutParams;
31 import android.widget.ImageView;
32 import android.widget.LinearLayout;
33 import com.google.android.setupcompat.internal.TemplateLayout;
34 import com.google.android.setupcompat.template.Mixin;
35 import com.google.android.setupdesign.GlifLayout;
36 import com.google.android.setupdesign.R;
37 import com.google.android.setupdesign.util.PartnerStyleHelper;
38 
39 /**
40  * A {@link com.google.android.setupcompat.template.Mixin} for setting an icon on the template
41  * layout.
42  */
43 public class IconMixin implements Mixin {
44 
45   private final TemplateLayout templateLayout;
46 
47   private final int originalHeight;
48   private final ImageView.ScaleType originalScaleType;
49 
50   /**
51    * @param layout The template layout that this Mixin is a part of.
52    * @param attrs XML attributes given to the layout.
53    * @param defStyleAttr The default style attribute as given to the constructor of the layout.
54    */
IconMixin(TemplateLayout layout, AttributeSet attrs, int defStyleAttr)55   public IconMixin(TemplateLayout layout, AttributeSet attrs, int defStyleAttr) {
56     templateLayout = layout;
57     final Context context = layout.getContext();
58 
59     ImageView iconView = getView();
60     if (iconView != null) {
61       LayoutParams layoutParams = iconView.getLayoutParams();
62       originalHeight = layoutParams.height;
63       originalScaleType = iconView.getScaleType();
64     } else {
65       originalHeight = 0;
66       originalScaleType = null;
67     }
68 
69     final TypedArray a =
70         context.obtainStyledAttributes(attrs, R.styleable.SudIconMixin, defStyleAttr, 0);
71 
72     final @DrawableRes int icon = a.getResourceId(R.styleable.SudIconMixin_android_icon, 0);
73     if (icon != 0) {
74       setIcon(icon);
75     }
76 
77     final boolean upscaleIcon = a.getBoolean(R.styleable.SudIconMixin_sudUpscaleIcon, false);
78     setUpscaleIcon(upscaleIcon);
79 
80     final @ColorInt int iconTint =
81         a.getColor(R.styleable.SudIconMixin_sudIconTint, Color.TRANSPARENT);
82     if (iconTint != Color.TRANSPARENT) {
83       setIconTint(iconTint);
84     }
85 
86     a.recycle();
87   }
88 
89   /** See {@link #applyPartnerCustomizationStyle(Context, ImageView)}. */
applyPartnerCustomizationStyle()90   public void applyPartnerCustomizationStyle() {
91     final Context context = templateLayout.getContext();
92     final ImageView iconImage = templateLayout.findManagedViewById(R.id.sud_layout_icon);
93     applyPartnerCustomizationStyle(context, iconImage);
94   }
95 
96   /**
97    * Use the given {@code iconImage} to apply heavy theme. If {@link
98    * com.google.android.setupdesign.GlifLayout#shouldApplyPartnerHeavyThemeResource()} is true,
99    * {@code iconImage} can be customized style from partner configuration.
100    *
101    * @param context The context of client activity.
102    * @param iconImage The icon image to use for apply heavy theme.
103    */
applyPartnerCustomizationStyle(Context context, @Nullable ImageView iconImage)104   private void applyPartnerCustomizationStyle(Context context, @Nullable ImageView iconImage) {
105     if (iconImage != null
106         && (templateLayout instanceof GlifLayout)
107         && ((GlifLayout) templateLayout).shouldApplyPartnerHeavyThemeResource()) {
108       int gravity = PartnerStyleHelper.getLayoutGravity(context);
109       if (gravity != 0) {
110         setGravity(iconImage, gravity);
111       }
112     }
113   }
114 
115   /**
116    * Sets the icon on this layout. The icon can also be set in XML using {@code android:icon}.
117    *
118    * @param icon A drawable icon.
119    */
setIcon(Drawable icon)120   public void setIcon(Drawable icon) {
121     final ImageView iconView = getView();
122     if (iconView != null) {
123       iconView.setImageDrawable(icon);
124       iconView.setVisibility(icon != null ? View.VISIBLE : View.GONE);
125     }
126   }
127 
128   /**
129    * Sets the icon on this layout. The icon can also be set in XML using {@code android:icon}.
130    *
131    * @param icon A drawable icon resource.
132    */
setIcon(@rawableRes int icon)133   public void setIcon(@DrawableRes int icon) {
134     final ImageView iconView = getView();
135     if (iconView != null) {
136       // Note: setImageResource on the ImageView is overridden in AppCompatImageView for
137       // support lib users, which enables vector drawable compat to work on versions pre-L.
138       iconView.setImageResource(icon);
139       iconView.setVisibility(icon != 0 ? View.VISIBLE : View.GONE);
140     }
141   }
142 
143   /** @return The icon previously set in {@link #setIcon(Drawable)} or {@code android:icon} */
getIcon()144   public Drawable getIcon() {
145     final ImageView iconView = getView();
146     return iconView != null ? iconView.getDrawable() : null;
147   }
148 
149   /** Forces the icon view to be as big as desired in the style. */
setUpscaleIcon(boolean shouldUpscaleIcon)150   public void setUpscaleIcon(boolean shouldUpscaleIcon) {
151     final int maxHeight;
152     final ImageView iconView = getView();
153     if (iconView != null) {
154       LayoutParams layoutParams = iconView.getLayoutParams();
155       if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
156         maxHeight = iconView.getMaxHeight();
157       } else {
158         maxHeight = (int) iconView.getResources().getDimension(R.dimen.sud_glif_icon_max_height);
159       }
160       layoutParams.height = shouldUpscaleIcon ? maxHeight : originalHeight;
161       iconView.setLayoutParams(layoutParams);
162       iconView.setScaleType(shouldUpscaleIcon ? ImageView.ScaleType.FIT_CENTER : originalScaleType);
163     }
164   }
165 
166   /** Tints the icon on this layout to the given color. */
setIconTint(@olorInt int tint)167   public void setIconTint(@ColorInt int tint) {
168     final ImageView iconView = getView();
169     if (iconView != null) {
170       iconView.setColorFilter(tint);
171     }
172   }
173 
174   /** Sets the content description of the icon view */
setContentDescription(CharSequence description)175   public void setContentDescription(CharSequence description) {
176     final ImageView iconView = getView();
177     if (iconView != null) {
178       iconView.setContentDescription(description);
179     }
180   }
181 
182   /** @return The content description of the icon view */
getContentDescription()183   public CharSequence getContentDescription() {
184     final ImageView iconView = getView();
185     return iconView != null ? iconView.getContentDescription() : null;
186   }
187 
188   /** @return The ImageView responsible for displaying the icon. */
getView()189   protected ImageView getView() {
190     return (ImageView) templateLayout.findManagedViewById(R.id.sud_layout_icon);
191   }
192 
setGravity(ImageView icon, int gravity)193   private void setGravity(ImageView icon, int gravity) {
194     if (icon.getLayoutParams() instanceof LinearLayout.LayoutParams) {
195       LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) icon.getLayoutParams();
196       layoutParams.gravity = gravity;
197       icon.setLayoutParams(layoutParams);
198     }
199   }
200 }
201