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