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