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 
Item()48   public Item() {
49     super();
50     layoutRes = getDefaultLayoutResource();
51   }
52 
Item(Context context, AttributeSet attrs)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 
getDefaultLayoutResource()67   protected int getDefaultLayoutResource() {
68     return R.layout.sud_items_default;
69   }
70 
setEnabled(boolean enabled)71   public void setEnabled(boolean enabled) {
72     this.enabled = enabled;
73     notifyItemChanged();
74   }
75 
76   @Override
getCount()77   public int getCount() {
78     return isVisible() ? 1 : 0;
79   }
80 
81   @Override
isEnabled()82   public boolean isEnabled() {
83     return enabled;
84   }
85 
setIcon(Drawable icon)86   public void setIcon(Drawable icon) {
87     this.icon = icon;
88     notifyItemChanged();
89   }
90 
getIcon()91   public Drawable getIcon() {
92     return icon;
93   }
94 
setIconTint(@olorInt int iconTint)95   public void setIconTint(@ColorInt int iconTint) {
96     this.iconTint = iconTint;
97   }
98 
99   @ColorInt
getIconTint()100   public int getIconTint() {
101     return iconTint;
102   }
103 
setIconGravity(int iconGravity)104   public void setIconGravity(int iconGravity) {
105     this.iconGravity = iconGravity;
106   }
107 
getIconGravity()108   public int getIconGravity() {
109     return iconGravity;
110   }
111 
setLayoutResource(int layoutResource)112   public void setLayoutResource(int layoutResource) {
113     layoutRes = layoutResource;
114     notifyItemChanged();
115   }
116 
117   @Override
getLayoutResource()118   public int getLayoutResource() {
119     return layoutRes;
120   }
121 
setSummary(CharSequence summary)122   public void setSummary(CharSequence summary) {
123     this.summary = summary;
124     notifyItemChanged();
125   }
126 
getSummary()127   public CharSequence getSummary() {
128     return summary;
129   }
130 
setTitle(CharSequence title)131   public void setTitle(CharSequence title) {
132     this.title = title;
133     notifyItemChanged();
134   }
135 
getTitle()136   public CharSequence getTitle() {
137     return title;
138   }
139 
setVisible(boolean visible)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 
isVisible()152   public boolean isVisible() {
153     return visible;
154   }
155 
156   @Override
getViewId()157   public int getViewId() {
158     return getId();
159   }
160 
161   @Override
onBindView(View view)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    */
onMergeIconStateAndLevels(ImageView iconView, Drawable icon)206   protected void onMergeIconStateAndLevels(ImageView iconView, Drawable icon) {
207     iconView.setImageState(icon.getState(), false /* merge */);
208     iconView.setImageLevel(icon.getLevel());
209   }
210 }
211