• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.android.systemui.qs;
18 
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.graphics.drawable.Drawable;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.os.Message;
25 import android.text.TextUtils;
26 import android.util.AttributeSet;
27 import android.util.Log;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.BaseAdapter;
32 import android.widget.FrameLayout;
33 import android.widget.ImageView;
34 import android.widget.TextView;
35 
36 import com.android.systemui.FontSizeUtils;
37 import com.android.systemui.R;
38 import com.android.systemui.plugins.qs.QSTile;
39 
40 /**
41  * Quick settings common detail view with line items.
42  */
43 public class QSDetailItems extends FrameLayout {
44     private static final String TAG = "QSDetailItems";
45     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
46 
47     private final int mQsDetailIconOverlaySize;
48     private final Context mContext;
49     private final H mHandler = new H();
50     private final Adapter mAdapter = new Adapter();
51 
52     private String mTag;
53     private Callback mCallback;
54     private boolean mItemsVisible = true;
55     private AutoSizingList mItemList;
56     private View mEmpty;
57     private TextView mEmptyText;
58     private ImageView mEmptyIcon;
59 
60     private Item[] mItems;
61 
QSDetailItems(Context context, AttributeSet attrs)62     public QSDetailItems(Context context, AttributeSet attrs) {
63         super(context, attrs);
64         mContext = context;
65         mTag = TAG;
66         mQsDetailIconOverlaySize = (int) getResources().getDimension(
67                 R.dimen.qs_detail_icon_overlay_size);
68     }
69 
convertOrInflate(Context context, View convert, ViewGroup parent)70     public static QSDetailItems convertOrInflate(Context context, View convert, ViewGroup parent) {
71         if (convert instanceof QSDetailItems) {
72             return (QSDetailItems) convert;
73         }
74         return (QSDetailItems) LayoutInflater.from(context).inflate(R.layout.qs_detail_items,
75                 parent, false);
76     }
77 
78     @Override
onFinishInflate()79     protected void onFinishInflate() {
80         super.onFinishInflate();
81         mItemList = findViewById(android.R.id.list);
82         mItemList.setVisibility(GONE);
83         mItemList.setAdapter(mAdapter);
84         mEmpty = findViewById(android.R.id.empty);
85         mEmpty.setVisibility(GONE);
86         mEmptyText = mEmpty.findViewById(android.R.id.title);
87         mEmptyIcon = mEmpty.findViewById(android.R.id.icon);
88     }
89 
90     @Override
onConfigurationChanged(Configuration newConfig)91     protected void onConfigurationChanged(Configuration newConfig) {
92         super.onConfigurationChanged(newConfig);
93         FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
94         int count = mItemList.getChildCount();
95         for (int i = 0; i < count; i++) {
96             View item = mItemList.getChildAt(i);
97             FontSizeUtils.updateFontSize(item, android.R.id.title,
98                     R.dimen.qs_detail_item_primary_text_size);
99             FontSizeUtils.updateFontSize(item, android.R.id.summary,
100                     R.dimen.qs_detail_item_secondary_text_size);
101         }
102     }
103 
setTagSuffix(String suffix)104     public void setTagSuffix(String suffix) {
105         mTag = TAG + "." + suffix;
106     }
107 
setEmptyState(int icon, int text)108     public void setEmptyState(int icon, int text) {
109         mEmptyIcon.post(() -> {
110             mEmptyIcon.setImageResource(icon);
111             mEmptyText.setText(text);
112         });
113     }
114 
115     @Override
onAttachedToWindow()116     protected void onAttachedToWindow() {
117         super.onAttachedToWindow();
118         if (DEBUG) Log.d(mTag, "onAttachedToWindow");
119     }
120 
121     @Override
onDetachedFromWindow()122     protected void onDetachedFromWindow() {
123         super.onDetachedFromWindow();
124         if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
125         mCallback = null;
126     }
127 
setCallback(Callback callback)128     public void setCallback(Callback callback) {
129         mHandler.removeMessages(H.SET_CALLBACK);
130         mHandler.obtainMessage(H.SET_CALLBACK, callback).sendToTarget();
131     }
132 
setItems(Item[] items)133     public void setItems(Item[] items) {
134         mHandler.removeMessages(H.SET_ITEMS);
135         mHandler.obtainMessage(H.SET_ITEMS, items).sendToTarget();
136     }
137 
setItemsVisible(boolean visible)138     public void setItemsVisible(boolean visible) {
139         mHandler.removeMessages(H.SET_ITEMS_VISIBLE);
140         mHandler.obtainMessage(H.SET_ITEMS_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
141     }
142 
handleSetCallback(Callback callback)143     private void handleSetCallback(Callback callback) {
144         mCallback = callback;
145     }
146 
handleSetItems(Item[] items)147     private void handleSetItems(Item[] items) {
148         final int itemCount = items != null ? items.length : 0;
149         mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
150         mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
151         mItems = items;
152         mAdapter.notifyDataSetChanged();
153     }
154 
handleSetItemsVisible(boolean visible)155     private void handleSetItemsVisible(boolean visible) {
156         if (mItemsVisible == visible) return;
157         mItemsVisible = visible;
158         for (int i = 0; i < mItemList.getChildCount(); i++) {
159             mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
160         }
161     }
162 
163     private class Adapter extends BaseAdapter {
164 
165         @Override
getCount()166         public int getCount() {
167             return mItems != null ? mItems.length : 0;
168         }
169 
170         @Override
getItem(int position)171         public Object getItem(int position) {
172             return mItems[position];
173         }
174 
175         @Override
getItemId(int position)176         public long getItemId(int position) {
177             return 0;
178         }
179 
180         @Override
getView(int position, View view, ViewGroup parent)181         public View getView(int position, View view, ViewGroup parent) {
182             final Item item = mItems[position];
183             if (view == null) {
184                 view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
185                         false);
186             }
187             view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
188             final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
189             if (item.icon != null) {
190                 iv.setImageDrawable(item.icon.getDrawable(iv.getContext()));
191             } else {
192                 iv.setImageResource(item.iconResId);
193             }
194             iv.getOverlay().clear();
195             if (item.overlay != null) {
196                 item.overlay.setBounds(0, 0, mQsDetailIconOverlaySize, mQsDetailIconOverlaySize);
197                 iv.getOverlay().add(item.overlay);
198             }
199             final TextView title = (TextView) view.findViewById(android.R.id.title);
200             title.setText(item.line1);
201             final TextView summary = (TextView) view.findViewById(android.R.id.summary);
202             final boolean twoLines = !TextUtils.isEmpty(item.line2);
203             title.setMaxLines(twoLines ? 1 : 2);
204             summary.setVisibility(twoLines ? VISIBLE : GONE);
205             summary.setText(twoLines ? item.line2 : null);
206             view.setOnClickListener(new OnClickListener() {
207                 @Override
208                 public void onClick(View v) {
209                     if (mCallback != null) {
210                         mCallback.onDetailItemClick(item);
211                     }
212                 }
213             });
214 
215             final ImageView icon2 = (ImageView) view.findViewById(android.R.id.icon2);
216             if (item.canDisconnect) {
217                 icon2.setImageResource(R.drawable.ic_qs_cancel);
218                 icon2.setVisibility(VISIBLE);
219                 icon2.setClickable(true);
220                 icon2.setOnClickListener(new OnClickListener() {
221                     @Override
222                     public void onClick(View v) {
223                         if (mCallback != null) {
224                             mCallback.onDetailItemDisconnect(item);
225                         }
226                     }
227                 });
228             } else if (item.icon2 != -1) {
229                 icon2.setVisibility(VISIBLE);
230                 icon2.setImageResource(item.icon2);
231                 icon2.setClickable(false);
232             } else {
233                 icon2.setVisibility(GONE);
234             }
235 
236             return view;
237         }
238     };
239 
240     private class H extends Handler {
241         private static final int SET_ITEMS = 1;
242         private static final int SET_CALLBACK = 2;
243         private static final int SET_ITEMS_VISIBLE = 3;
244 
H()245         public H() {
246             super(Looper.getMainLooper());
247         }
248 
249         @Override
handleMessage(Message msg)250         public void handleMessage(Message msg) {
251             if (msg.what == SET_ITEMS) {
252                 handleSetItems((Item[]) msg.obj);
253             } else if (msg.what == SET_CALLBACK) {
254                 handleSetCallback((QSDetailItems.Callback) msg.obj);
255             } else if (msg.what == SET_ITEMS_VISIBLE) {
256                 handleSetItemsVisible(msg.arg1 != 0);
257             }
258         }
259     }
260 
261     public static class Item {
262         public int iconResId;
263         public QSTile.Icon icon;
264         public Drawable overlay;
265         public CharSequence line1;
266         public CharSequence line2;
267         public Object tag;
268         public boolean canDisconnect;
269         public int icon2 = -1;
270     }
271 
272     public interface Callback {
onDetailItemClick(Item item)273         void onDetailItemClick(Item item);
onDetailItemDisconnect(Item item)274         void onDetailItemDisconnect(Item item);
275     }
276 }
277