2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.systemui.qs;
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.util.AttributeSet;
22 import android.view.Gravity;
23 import android.view.View;
24 import android.widget.LinearLayout;
25 import android.widget.Space;
27 import com.android.systemui.R;
28 import com.android.systemui.qs.QSTile.SignalState;
29 import com.android.systemui.qs.QSTile.State;
30 import com.android.systemui.qs.customize.QSCustomizer;
31 import com.android.systemui.statusbar.phone.QSTileHost;
32 import com.android.systemui.tuner.TunerService;
33 import com.android.systemui.tuner.TunerService.Tunable;
35 import java.util.ArrayList;
36 import java.util.Collection;
39 * Version of QSPanel that only shows N Quick Tiles in the QS Header.
41 public class QuickQSPanel extends QSPanel {
43 public static final String NUM_QUICK_TILES = "sysui_qqs_count";
45 private int mMaxTiles;
46 private QSPanel mFullPanel;
49 public QuickQSPanel(Context context, AttributeSet attrs) {
50 super(context, attrs);
51 if (mTileLayout != null) {
52 for (int i = 0; i < mRecords.size(); i++) {
53 mTileLayout.removeTile(mRecords.get(i));
55 removeView((View) mTileLayout);
57 mTileLayout = new HeaderTileLayout(context);
58 mTileLayout.setListening(mListening);
59 addView((View) mTileLayout, 1 /* Between brightness and footer */);
63 protected void onAttachedToWindow() {
64 super.onAttachedToWindow();
65 TunerService.get(mContext).addTunable(mNumTiles, NUM_QUICK_TILES);
69 protected void onDetachedFromWindow() {
70 super.onDetachedFromWindow();
71 TunerService.get(mContext).removeTunable(mNumTiles);
74 public void setQSPanelAndHeader(QSPanel fullPanel, View header) {
75 mFullPanel = fullPanel;
80 protected boolean shouldShowDetail() {
85 protected void drawTile(TileRecord r, State state) {
86 if (state instanceof SignalState) {
87 State copy = r.tile.newTileState();
89 // No activity shown in the quick panel.
90 ((SignalState) copy).activityIn = false;
91 ((SignalState) copy).activityOut = false;
94 super.drawTile(r, state);
98 protected QSTileBaseView createTileView(QSTile<?> tile, boolean collapsedView) {
99 return new QSTileBaseView(mContext, tile.createTileView(mContext), collapsedView);
103 public void setHost(QSTileHost host, QSCustomizer customizer) {
104 super.setHost(host, customizer);
105 setTiles(mHost.getTiles());
108 public void setMaxTiles(int maxTiles) {
109 mMaxTiles = maxTiles;
111 setTiles(mHost.getTiles());
116 protected void onTileClick(QSTile<?> tile) {
117 tile.secondaryClick();
121 public void onTuningChanged(String key, String newValue) {
122 // No tunings for you.
123 if (key.equals(QS_SHOW_BRIGHTNESS)) {
124 // No Brightness for you.
125 super.onTuningChanged(key, "0");
130 public void setTiles(Collection<QSTile<?>> tiles) {
131 ArrayList<QSTile<?>> quickTiles = new ArrayList<>();
132 for (QSTile<?> tile : tiles) {
133 quickTiles.add(tile);
134 if (quickTiles.size() == mMaxTiles) {
138 super.setTiles(quickTiles, true);
141 private final Tunable mNumTiles = new Tunable() {
143 public void onTuningChanged(String key, String newValue) {
144 setMaxTiles(getNumQuickTiles(mContext));
148 public int getNumQuickTiles(Context context) {
149 return TunerService.get(context).getValue(NUM_QUICK_TILES, 6);
152 private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
154 protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
155 private boolean mListening;
157 public HeaderTileLayout(Context context) {
159 setClipChildren(false);
160 setClipToPadding(false);
161 setGravity(Gravity.CENTER_VERTICAL);
162 setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
166 public void setListening(boolean listening) {
167 if (mListening == listening) return;
168 mListening = listening;
169 for (TileRecord record : mRecords) {
170 record.tile.setListening(this, mListening);
175 public void addTile(TileRecord tile) {
176 if (getChildCount() != 0) {
178 addView(new Space(mContext), getChildCount(), generateSpaceParams());
180 addView(tile.tileView, getChildCount(), generateLayoutParams());
182 tile.tile.setListening(this, mListening);
185 private LayoutParams generateSpaceParams() {
186 int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
187 LayoutParams lp = new LayoutParams(0, size);
189 lp.gravity = Gravity.CENTER;
193 private LayoutParams generateLayoutParams() {
194 int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
195 LayoutParams lp = new LayoutParams(size, size);
196 lp.gravity = Gravity.CENTER;
201 public void removeTile(TileRecord tile) {
202 int childIndex = getChildIndex(tile.tileView);
204 removeViewAt(childIndex);
205 if (getChildCount() != 0) {
206 // Remove its spacer as well.
207 removeViewAt(childIndex);
209 mRecords.remove(tile);
210 tile.tile.setListening(this, false);
213 private int getChildIndex(QSTileBaseView tileView) {
214 final int N = getChildCount();
215 for (int i = 0; i < N; i++) {
216 if (getChildAt(i) == tileView) {
224 public int getOffsetTop(TileRecord tile) {
229 public boolean updateResources() {
230 // No resources here.
235 public boolean hasOverlappingRendering() {
240 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
241 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
242 if (mRecords != null && mRecords.size() > 0) {
243 View previousView = this;
244 for (TileRecord record : mRecords) {
245 if (record.tileView.getVisibility() == GONE) continue;
246 previousView = record.tileView.updateAccessibilityOrder(previousView);
248 mRecords.get(0).tileView.setAccessibilityTraversalAfter(
249 R.id.alarm_status_collapsed);
250 mRecords.get(mRecords.size() - 1).tileView.setAccessibilityTraversalBefore(
251 R.id.expand_indicator);