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