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.google.android.setupdesign.items; 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.util.AttributeSet; 24 import android.view.Gravity; 25 import android.view.View; 26 import android.view.ViewGroup.LayoutParams; 27 import android.widget.ImageView; 28 import android.widget.LinearLayout; 29 import android.widget.TextView; 30 import androidx.annotation.ColorInt; 31 import androidx.annotation.Nullable; 32 import com.google.android.setupdesign.R; 33 import com.google.android.setupdesign.util.ItemStyler; 34 import com.google.android.setupdesign.util.LayoutStyler; 35 36 /** 37 * Definition of an item in an {@link ItemHierarchy}. An item is usually defined in XML and inflated 38 * using {@link ItemInflater}. 39 */ 40 public class Item extends AbstractItem { 41 42 private boolean enabled = true; 43 @Nullable private Drawable icon; 44 private int layoutRes; 45 @Nullable private CharSequence summary; 46 @Nullable private CharSequence title; 47 @Nullable private CharSequence contentDescription; 48 private boolean visible = true; 49 @ColorInt private int iconTint = Color.TRANSPARENT; 50 private int iconGravity = Gravity.CENTER_VERTICAL; 51 Item()52 public Item() { 53 super(); 54 layoutRes = getDefaultLayoutResource(); 55 } 56 Item(Context context, AttributeSet attrs)57 public Item(Context context, AttributeSet attrs) { 58 super(context, attrs); 59 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SudItem); 60 enabled = a.getBoolean(R.styleable.SudItem_android_enabled, true); 61 icon = a.getDrawable(R.styleable.SudItem_android_icon); 62 title = a.getText(R.styleable.SudItem_android_title); 63 summary = a.getText(R.styleable.SudItem_android_summary); 64 contentDescription = a.getText(R.styleable.SudItem_android_contentDescription); 65 layoutRes = a.getResourceId(R.styleable.SudItem_android_layout, getDefaultLayoutResource()); 66 visible = a.getBoolean(R.styleable.SudItem_android_visible, true); 67 iconTint = a.getColor(R.styleable.SudItem_sudIconTint, Color.TRANSPARENT); 68 iconGravity = a.getInt(R.styleable.SudItem_sudIconGravity, Gravity.CENTER_VERTICAL); 69 70 a.recycle(); 71 } 72 getDefaultLayoutResource()73 protected int getDefaultLayoutResource() { 74 return R.layout.sud_items_default; 75 } 76 setEnabled(boolean enabled)77 public void setEnabled(boolean enabled) { 78 this.enabled = enabled; 79 notifyItemChanged(); 80 } 81 82 @Override getCount()83 public int getCount() { 84 return isVisible() ? 1 : 0; 85 } 86 87 @Override isEnabled()88 public boolean isEnabled() { 89 return enabled; 90 } 91 setIcon(@ullable Drawable icon)92 public void setIcon(@Nullable Drawable icon) { 93 this.icon = icon; 94 notifyItemChanged(); 95 } 96 97 @Nullable getIcon()98 public Drawable getIcon() { 99 return icon; 100 } 101 setIconTint(@olorInt int iconTint)102 public void setIconTint(@ColorInt int iconTint) { 103 this.iconTint = iconTint; 104 } 105 106 @ColorInt getIconTint()107 public int getIconTint() { 108 return iconTint; 109 } 110 setIconGravity(int iconGravity)111 public void setIconGravity(int iconGravity) { 112 this.iconGravity = iconGravity; 113 } 114 getIconGravity()115 public int getIconGravity() { 116 return iconGravity; 117 } 118 setLayoutResource(int layoutResource)119 public void setLayoutResource(int layoutResource) { 120 layoutRes = layoutResource; 121 notifyItemChanged(); 122 } 123 124 @Override getLayoutResource()125 public int getLayoutResource() { 126 return layoutRes; 127 } 128 setSummary(@ullable CharSequence summary)129 public void setSummary(@Nullable CharSequence summary) { 130 this.summary = summary; 131 notifyItemChanged(); 132 } 133 134 @Nullable getSummary()135 public CharSequence getSummary() { 136 return summary; 137 } 138 setTitle(@ullable CharSequence title)139 public void setTitle(@Nullable CharSequence title) { 140 this.title = title; 141 notifyItemChanged(); 142 } 143 144 @Nullable getTitle()145 public CharSequence getTitle() { 146 return title; 147 } 148 149 @Nullable getContentDescription()150 public CharSequence getContentDescription() { 151 return contentDescription; 152 } 153 setContentDescription(@ullable CharSequence contentDescription)154 public void setContentDescription(@Nullable CharSequence contentDescription) { 155 this.contentDescription = contentDescription; 156 notifyItemChanged(); 157 } 158 setVisible(boolean visible)159 public void setVisible(boolean visible) { 160 if (this.visible == visible) { 161 return; 162 } 163 this.visible = visible; 164 if (!visible) { 165 notifyItemRangeRemoved(0, 1); 166 } else { 167 notifyItemRangeInserted(0, 1); 168 } 169 } 170 isVisible()171 public boolean isVisible() { 172 return visible; 173 } 174 hasSummary(CharSequence summary)175 private boolean hasSummary(CharSequence summary) { 176 return summary != null && summary.length() > 0; 177 } 178 179 @Override getViewId()180 public int getViewId() { 181 return getId(); 182 } 183 184 @Override onBindView(View view)185 public void onBindView(View view) { 186 TextView label = (TextView) view.findViewById(R.id.sud_items_title); 187 label.setText(getTitle()); 188 189 TextView summaryView = (TextView) view.findViewById(R.id.sud_items_summary); 190 CharSequence summary = getSummary(); 191 if (hasSummary(summary)) { 192 summaryView.setText(summary); 193 summaryView.setVisibility(View.VISIBLE); 194 } else { 195 summaryView.setVisibility(View.GONE); 196 } 197 198 view.setContentDescription(getContentDescription()); 199 200 final View iconContainer = view.findViewById(R.id.sud_items_icon_container); 201 final Drawable icon = getIcon(); 202 if (icon != null) { 203 final ImageView iconView = (ImageView) view.findViewById(R.id.sud_items_icon); 204 // Set the image drawable to null before setting the state and level to avoid affecting 205 // any recycled drawable in the ImageView 206 iconView.setImageDrawable(null); 207 onMergeIconStateAndLevels(iconView, icon); 208 iconView.setImageDrawable(icon); 209 if (iconTint != Color.TRANSPARENT) { 210 iconView.setColorFilter(iconTint); 211 } else { 212 iconView.clearColorFilter(); 213 } 214 LayoutParams layoutParams = iconContainer.getLayoutParams(); 215 if (layoutParams instanceof LinearLayout.LayoutParams) { 216 ((LinearLayout.LayoutParams) layoutParams).gravity = iconGravity; 217 } 218 iconContainer.setVisibility(View.VISIBLE); 219 } else { 220 iconContainer.setVisibility(View.GONE); 221 } 222 223 view.setId(getViewId()); 224 225 // ExpandableSwitchItem uses its child view to apply the style SudItemContainer. It is not 226 // possible to directly adjust the padding start/end of the item's layout here. It needs to 227 // get its child view to adjust it first, so skip the Layout padding adjustment. 228 // If the item view is a header layout, it doesn't need to adjust the layout padding start/end 229 // here. It will be adjusted by HeaderMixin. 230 // TODO: Add partner resource enable check 231 if (!(this instanceof ExpandableSwitchItem) && view.getId() != R.id.sud_layout_header) { 232 LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(view); 233 } 234 ItemStyler.applyPartnerCustomizationItemStyle(view); 235 } 236 237 /** 238 * Copies state and level information from {@link #getIcon()} to the currently bound view's 239 * ImageView. Subclasses can override this method to change whats being copied from the icon to 240 * the ImageView. 241 */ onMergeIconStateAndLevels(ImageView iconView, Drawable icon)242 protected void onMergeIconStateAndLevels(ImageView iconView, Drawable icon) { 243 iconView.setImageState(icon.getState(), false /* merge */); 244 iconView.setImageLevel(icon.getLevel()); 245 } 246 } 247