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