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