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