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