1 /* 2 * Copyright (C) 2015 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.util.AttributeSet; 21 import android.view.Gravity; 22 import android.view.View; 23 import android.widget.LinearLayout; 24 import android.widget.Space; 25 26 import com.android.systemui.Dependency; 27 import com.android.systemui.R; 28 import com.android.systemui.plugins.qs.*; 29 import com.android.systemui.plugins.qs.QSTile.SignalState; 30 import com.android.systemui.plugins.qs.QSTile.State; 31 import com.android.systemui.plugins.qs.QSTileView; 32 import com.android.systemui.qs.customize.QSCustomizer; 33 import com.android.systemui.tuner.TunerService; 34 import com.android.systemui.tuner.TunerService.Tunable; 35 36 import java.util.ArrayList; 37 import java.util.Collection; 38 39 /** 40 * Version of QSPanel that only shows N Quick Tiles in the QS Header. 41 */ 42 public class QuickQSPanel extends QSPanel { 43 44 public static final String NUM_QUICK_TILES = "sysui_qqs_count"; 45 46 private int mMaxTiles; 47 protected QSPanel mFullPanel; 48 QuickQSPanel(Context context, AttributeSet attrs)49 public QuickQSPanel(Context context, AttributeSet attrs) { 50 super(context, attrs); 51 if (mFooter != null) { 52 removeView((View) mFooter.getView()); 53 } 54 if (mTileLayout != null) { 55 for (int i = 0; i < mRecords.size(); i++) { 56 mTileLayout.removeTile(mRecords.get(i)); 57 } 58 removeView((View) mTileLayout); 59 } 60 mTileLayout = new HeaderTileLayout(context); 61 mTileLayout.setListening(mListening); 62 addView((View) mTileLayout, 0 /* Between brightness and footer */); 63 super.setPadding(0, 0, 0, 0); 64 } 65 66 @Override setPadding(int left, int top, int right, int bottom)67 public void setPadding(int left, int top, int right, int bottom) { 68 // Always have no padding. 69 } 70 71 @Override addDivider()72 protected void addDivider() { 73 } 74 75 @Override onAttachedToWindow()76 protected void onAttachedToWindow() { 77 super.onAttachedToWindow(); 78 Dependency.get(TunerService.class).addTunable(mNumTiles, NUM_QUICK_TILES); 79 } 80 81 @Override onDetachedFromWindow()82 protected void onDetachedFromWindow() { 83 super.onDetachedFromWindow(); 84 Dependency.get(TunerService.class).removeTunable(mNumTiles); 85 } 86 setQSPanelAndHeader(QSPanel fullPanel, View header)87 public void setQSPanelAndHeader(QSPanel fullPanel, View header) { 88 mFullPanel = fullPanel; 89 } 90 91 @Override shouldShowDetail()92 protected boolean shouldShowDetail() { 93 return !mExpanded; 94 } 95 96 @Override drawTile(TileRecord r, State state)97 protected void drawTile(TileRecord r, State state) { 98 if (state instanceof SignalState) { 99 SignalState copy = new SignalState(); 100 state.copyTo(copy); 101 // No activity shown in the quick panel. 102 copy.activityIn = false; 103 copy.activityOut = false; 104 state = copy; 105 } 106 super.drawTile(r, state); 107 } 108 109 @Override setHost(QSTileHost host, QSCustomizer customizer)110 public void setHost(QSTileHost host, QSCustomizer customizer) { 111 super.setHost(host, customizer); 112 setTiles(mHost.getTiles()); 113 } 114 setMaxTiles(int maxTiles)115 public void setMaxTiles(int maxTiles) { 116 mMaxTiles = maxTiles; 117 if (mHost != null) { 118 setTiles(mHost.getTiles()); 119 } 120 } 121 122 @Override onTuningChanged(String key, String newValue)123 public void onTuningChanged(String key, String newValue) { 124 // No tunings for you. 125 if (key.equals(QS_SHOW_BRIGHTNESS)) { 126 // No Brightness for you. 127 super.onTuningChanged(key, "0"); 128 } 129 } 130 131 @Override setTiles(Collection<QSTile> tiles)132 public void setTiles(Collection<QSTile> tiles) { 133 ArrayList<QSTile> quickTiles = new ArrayList<>(); 134 for (QSTile tile : tiles) { 135 quickTiles.add(tile); 136 if (quickTiles.size() == mMaxTiles) { 137 break; 138 } 139 } 140 super.setTiles(quickTiles, true); 141 } 142 143 private final Tunable mNumTiles = new Tunable() { 144 @Override 145 public void onTuningChanged(String key, String newValue) { 146 setMaxTiles(getNumQuickTiles(mContext)); 147 } 148 }; 149 getNumQuickTiles(Context context)150 public static int getNumQuickTiles(Context context) { 151 return Dependency.get(TunerService.class).getValue(NUM_QUICK_TILES, 6); 152 } 153 154 private static class HeaderTileLayout extends LinearLayout implements QSTileLayout { 155 156 protected final ArrayList<TileRecord> mRecords = new ArrayList<>(); 157 private boolean mListening; 158 HeaderTileLayout(Context context)159 public HeaderTileLayout(Context context) { 160 super(context); 161 setClipChildren(false); 162 setClipToPadding(false); 163 setGravity(Gravity.CENTER_VERTICAL); 164 setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 165 } 166 167 @Override setListening(boolean listening)168 public void setListening(boolean listening) { 169 if (mListening == listening) return; 170 mListening = listening; 171 for (TileRecord record : mRecords) { 172 record.tile.setListening(this, mListening); 173 } 174 } 175 176 @Override addTile(TileRecord tile)177 public void addTile(TileRecord tile) { 178 if (getChildCount() != 0) { 179 // Add a spacer. 180 addView(new Space(mContext), getChildCount(), generateSpaceParams()); 181 } 182 addView(tile.tileView, getChildCount(), generateLayoutParams()); 183 mRecords.add(tile); 184 tile.tile.setListening(this, mListening); 185 } 186 generateSpaceParams()187 private LayoutParams generateSpaceParams() { 188 int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size); 189 LayoutParams lp = new LayoutParams(0, size); 190 lp.weight = 1; 191 lp.gravity = Gravity.CENTER; 192 return lp; 193 } 194 generateLayoutParams()195 private LayoutParams generateLayoutParams() { 196 int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size); 197 LayoutParams lp = new LayoutParams(size, size); 198 lp.gravity = Gravity.CENTER; 199 return lp; 200 } 201 202 @Override removeTile(TileRecord tile)203 public void removeTile(TileRecord tile) { 204 int childIndex = getChildIndex(tile.tileView); 205 // Remove the tile. 206 removeViewAt(childIndex); 207 if (getChildCount() != 0) { 208 // Remove its spacer as well. 209 removeViewAt(childIndex); 210 } 211 mRecords.remove(tile); 212 tile.tile.setListening(this, false); 213 } 214 getChildIndex(QSTileView tileView)215 private int getChildIndex(QSTileView tileView) { 216 final int N = getChildCount(); 217 for (int i = 0; i < N; i++) { 218 if (getChildAt(i) == tileView) { 219 return i; 220 } 221 } 222 return -1; 223 } 224 225 @Override getOffsetTop(TileRecord tile)226 public int getOffsetTop(TileRecord tile) { 227 return 0; 228 } 229 230 @Override updateResources()231 public boolean updateResources() { 232 // No resources here. 233 return false; 234 } 235 236 @Override hasOverlappingRendering()237 public boolean hasOverlappingRendering() { 238 return false; 239 } 240 241 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)242 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 243 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 244 if (mRecords != null && mRecords.size() > 0) { 245 View previousView = this; 246 for (TileRecord record : mRecords) { 247 if (record.tileView.getVisibility() == GONE) continue; 248 previousView = record.tileView.updateAccessibilityOrder(previousView); 249 } 250 mRecords.get(0).tileView.setAccessibilityTraversalAfter( 251 R.id.alarm_status_collapsed); 252 mRecords.get(mRecords.size() - 1).tileView.setAccessibilityTraversalBefore( 253 R.id.expand_indicator); 254 } 255 } 256 } 257 } 258