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