blob: ddd9910232739d4d0b267b754411fb1abda7c20e [file] [log] [blame]
John Spurlock486b78e2014-07-07 08:37:56 -04001/*
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
17package com.android.systemui.qs;
18
19import android.content.Context;
Jorim Jaggie17c4b42014-08-26 17:27:31 +020020import android.content.res.Configuration;
Jason Monkb27ec6d32014-12-01 17:50:16 -050021import android.graphics.drawable.Drawable;
John Spurlock486b78e2014-07-07 08:37:56 -040022import android.os.Handler;
23import android.os.Looper;
24import android.os.Message;
25import android.text.TextUtils;
26import android.util.AttributeSet;
27import android.util.Log;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.ViewGroup;
Jason Monk6573ef22016-04-06 12:37:18 -040031import android.widget.BaseAdapter;
John Spurlock486b78e2014-07-07 08:37:56 -040032import android.widget.FrameLayout;
33import android.widget.ImageView;
John Spurlock486b78e2014-07-07 08:37:56 -040034import android.widget.TextView;
Jorim Jaggie17c4b42014-08-26 17:27:31 +020035import com.android.systemui.FontSizeUtils;
John Spurlock486b78e2014-07-07 08:37:56 -040036import com.android.systemui.R;
jackqdyulei4b7f43b2017-10-19 11:05:09 -070037import com.android.systemui.plugins.qs.QSTile;
John Spurlock486b78e2014-07-07 08:37:56 -040038
39/**
40 * Quick settings common detail view with line items.
41 */
42public class QSDetailItems extends FrameLayout {
43 private static final String TAG = "QSDetailItems";
44 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
45
Muyuan Li72a63872016-05-14 11:35:41 -070046 private final int mQsDetailIconOverlaySize;
John Spurlock486b78e2014-07-07 08:37:56 -040047 private final Context mContext;
48 private final H mHandler = new H();
Jason Monk6573ef22016-04-06 12:37:18 -040049 private final Adapter mAdapter = new Adapter();
John Spurlock486b78e2014-07-07 08:37:56 -040050
51 private String mTag;
52 private Callback mCallback;
53 private boolean mItemsVisible = true;
Jason Monk6573ef22016-04-06 12:37:18 -040054 private AutoSizingList mItemList;
John Spurlock486b78e2014-07-07 08:37:56 -040055 private View mEmpty;
56 private TextView mEmptyText;
57 private ImageView mEmptyIcon;
Jason Monk6573ef22016-04-06 12:37:18 -040058
59 private Item[] mItems;
John Spurlock486b78e2014-07-07 08:37:56 -040060
61 public QSDetailItems(Context context, AttributeSet attrs) {
62 super(context, attrs);
63 mContext = context;
64 mTag = TAG;
Muyuan Li72a63872016-05-14 11:35:41 -070065 mQsDetailIconOverlaySize = (int) getResources().getDimension(
66 R.dimen.qs_detail_icon_overlay_size);
John Spurlock486b78e2014-07-07 08:37:56 -040067 }
68
69 public static QSDetailItems convertOrInflate(Context context, View convert, ViewGroup parent) {
70 if (convert instanceof QSDetailItems) {
71 return (QSDetailItems) convert;
72 }
73 return (QSDetailItems) LayoutInflater.from(context).inflate(R.layout.qs_detail_items,
74 parent, false);
75 }
76
77 @Override
78 protected void onFinishInflate() {
79 super.onFinishInflate();
Alan Viverette51efddb2017-04-05 10:00:01 -040080 mItemList = findViewById(android.R.id.list);
Jason Monk6573ef22016-04-06 12:37:18 -040081 mItemList.setVisibility(GONE);
82 mItemList.setAdapter(mAdapter);
John Spurlock486b78e2014-07-07 08:37:56 -040083 mEmpty = findViewById(android.R.id.empty);
84 mEmpty.setVisibility(GONE);
Jason Monkbe3235a2017-04-05 09:29:53 -040085 mEmptyText = mEmpty.findViewById(android.R.id.title);
86 mEmptyIcon = mEmpty.findViewById(android.R.id.icon);
John Spurlock486b78e2014-07-07 08:37:56 -040087 }
88
Jorim Jaggie17c4b42014-08-26 17:27:31 +020089 @Override
90 protected void onConfigurationChanged(Configuration newConfig) {
91 super.onConfigurationChanged(newConfig);
92 FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
Jason Monk6573ef22016-04-06 12:37:18 -040093 int count = mItemList.getChildCount();
Jorim Jaggie17c4b42014-08-26 17:27:31 +020094 for (int i = 0; i < count; i++) {
Jason Monk6573ef22016-04-06 12:37:18 -040095 View item = mItemList.getChildAt(i);
Jorim Jaggie17c4b42014-08-26 17:27:31 +020096 FontSizeUtils.updateFontSize(item, android.R.id.title,
97 R.dimen.qs_detail_item_primary_text_size);
98 FontSizeUtils.updateFontSize(item, android.R.id.summary,
99 R.dimen.qs_detail_item_secondary_text_size);
100 }
101 }
102
John Spurlock486b78e2014-07-07 08:37:56 -0400103 public void setTagSuffix(String suffix) {
104 mTag = TAG + "." + suffix;
105 }
106
107 public void setEmptyState(int icon, int text) {
Jason Monkbe3235a2017-04-05 09:29:53 -0400108 mEmptyIcon.post(() -> {
109 mEmptyIcon.setImageResource(icon);
110 mEmptyText.setText(text);
111 });
John Spurlock486b78e2014-07-07 08:37:56 -0400112 }
113
114 @Override
115 protected void onAttachedToWindow() {
116 super.onAttachedToWindow();
117 if (DEBUG) Log.d(mTag, "onAttachedToWindow");
118 }
119
120 @Override
121 protected void onDetachedFromWindow() {
122 super.onDetachedFromWindow();
123 if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
124 mCallback = null;
125 }
126
127 public void setCallback(Callback callback) {
128 mHandler.removeMessages(H.SET_CALLBACK);
129 mHandler.obtainMessage(H.SET_CALLBACK, callback).sendToTarget();
130 }
131
132 public void setItems(Item[] items) {
133 mHandler.removeMessages(H.SET_ITEMS);
134 mHandler.obtainMessage(H.SET_ITEMS, items).sendToTarget();
135 }
136
137 public void setItemsVisible(boolean visible) {
138 mHandler.removeMessages(H.SET_ITEMS_VISIBLE);
139 mHandler.obtainMessage(H.SET_ITEMS_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
140 }
141
142 private void handleSetCallback(Callback callback) {
143 mCallback = callback;
144 }
145
146 private void handleSetItems(Item[] items) {
Jason Monk6573ef22016-04-06 12:37:18 -0400147 final int itemCount = items != null ? items.length : 0;
John Spurlock486b78e2014-07-07 08:37:56 -0400148 mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
Jason Monk6573ef22016-04-06 12:37:18 -0400149 mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
150 mItems = items;
151 mAdapter.notifyDataSetChanged();
John Spurlock486b78e2014-07-07 08:37:56 -0400152 }
153
154 private void handleSetItemsVisible(boolean visible) {
155 if (mItemsVisible == visible) return;
156 mItemsVisible = visible;
Jason Monk6573ef22016-04-06 12:37:18 -0400157 for (int i = 0; i < mItemList.getChildCount(); i++) {
158 mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
John Spurlock486b78e2014-07-07 08:37:56 -0400159 }
160 }
161
Jason Monk6573ef22016-04-06 12:37:18 -0400162 private class Adapter extends BaseAdapter {
163
164 @Override
165 public int getCount() {
166 return mItems != null ? mItems.length : 0;
John Spurlock486b78e2014-07-07 08:37:56 -0400167 }
Jason Monk6573ef22016-04-06 12:37:18 -0400168
169 @Override
170 public Object getItem(int position) {
171 return mItems[position];
Jason Monkb27ec6d32014-12-01 17:50:16 -0500172 }
Jason Monk6573ef22016-04-06 12:37:18 -0400173
174 @Override
175 public long getItemId(int position) {
176 return 0;
177 }
178
179 @Override
180 public View getView(int position, View view, ViewGroup parent) {
181 final Item item = mItems[position];
182 if (view == null) {
183 view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
184 false);
John Spurlock486b78e2014-07-07 08:37:56 -0400185 }
Jason Monk6573ef22016-04-06 12:37:18 -0400186 view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
187 final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
jackqdyulei786a4902017-10-24 13:27:53 -0700188 if (item.icon != null) {
189 iv.setImageDrawable(item.icon.getDrawable(iv.getContext()));
Jason Monk3fd0b142017-08-30 18:11:21 -0400190 } else {
jackqdyulei786a4902017-10-24 13:27:53 -0700191 iv.setImageResource(item.iconResId);
Jason Monk3fd0b142017-08-30 18:11:21 -0400192 }
Jason Monk6573ef22016-04-06 12:37:18 -0400193 iv.getOverlay().clear();
194 if (item.overlay != null) {
Muyuan Li72a63872016-05-14 11:35:41 -0700195 item.overlay.setBounds(0, 0, mQsDetailIconOverlaySize, mQsDetailIconOverlaySize);
Jason Monk6573ef22016-04-06 12:37:18 -0400196 iv.getOverlay().add(item.overlay);
John Spurlock486b78e2014-07-07 08:37:56 -0400197 }
Jason Monk6573ef22016-04-06 12:37:18 -0400198 final TextView title = (TextView) view.findViewById(android.R.id.title);
199 title.setText(item.line1);
200 final TextView summary = (TextView) view.findViewById(android.R.id.summary);
201 final boolean twoLines = !TextUtils.isEmpty(item.line2);
202 title.setMaxLines(twoLines ? 1 : 2);
203 summary.setVisibility(twoLines ? VISIBLE : GONE);
204 summary.setText(twoLines ? item.line2 : null);
205 view.setOnClickListener(new OnClickListener() {
206 @Override
207 public void onClick(View v) {
208 if (mCallback != null) {
209 mCallback.onDetailItemClick(item);
210 }
211 }
212 });
Sundeep Ghumanff0f1082017-02-10 11:49:36 -0800213
214 final ImageView icon2 = (ImageView) view.findViewById(android.R.id.icon2);
215 if (item.canDisconnect) {
216 icon2.setImageResource(R.drawable.ic_qs_cancel);
217 icon2.setVisibility(VISIBLE);
218 icon2.setClickable(true);
219 icon2.setOnClickListener(new OnClickListener() {
220 @Override
221 public void onClick(View v) {
222 if (mCallback != null) {
223 mCallback.onDetailItemDisconnect(item);
224 }
Jason Monk6573ef22016-04-06 12:37:18 -0400225 }
Sundeep Ghumanff0f1082017-02-10 11:49:36 -0800226 });
227 } else if (item.icon2 != -1) {
228 icon2.setVisibility(VISIBLE);
229 icon2.setImageResource(item.icon2);
230 icon2.setClickable(false);
231 } else {
232 icon2.setVisibility(GONE);
233 }
234
Jason Monk6573ef22016-04-06 12:37:18 -0400235 return view;
236 }
237 };
John Spurlock486b78e2014-07-07 08:37:56 -0400238
239 private class H extends Handler {
240 private static final int SET_ITEMS = 1;
241 private static final int SET_CALLBACK = 2;
242 private static final int SET_ITEMS_VISIBLE = 3;
243
244 public H() {
245 super(Looper.getMainLooper());
246 }
247
248 @Override
249 public void handleMessage(Message msg) {
250 if (msg.what == SET_ITEMS) {
251 handleSetItems((Item[]) msg.obj);
252 } else if (msg.what == SET_CALLBACK) {
253 handleSetCallback((QSDetailItems.Callback) msg.obj);
254 } else if (msg.what == SET_ITEMS_VISIBLE) {
255 handleSetItemsVisible(msg.arg1 != 0);
256 }
257 }
258 }
259
260 public static class Item {
jackqdyulei786a4902017-10-24 13:27:53 -0700261 public int iconResId;
262 public QSTile.Icon icon;
Jason Monkb27ec6d32014-12-01 17:50:16 -0500263 public Drawable overlay;
Jason Monk6980d122015-06-15 10:07:55 -0400264 public CharSequence line1;
265 public CharSequence line2;
John Spurlock486b78e2014-07-07 08:37:56 -0400266 public Object tag;
267 public boolean canDisconnect;
Sundeep Ghumanff0f1082017-02-10 11:49:36 -0800268 public int icon2 = -1;
John Spurlock486b78e2014-07-07 08:37:56 -0400269 }
270
271 public interface Callback {
272 void onDetailItemClick(Item item);
273 void onDetailItemDisconnect(Item item);
274 }
275}