StatusBarHeaderView.java revision 8ddb2da8759c29b3968b4d6bb9488f59a19f0ff2
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
17package com.android.systemui.statusbar.phone;
18
19import android.content.Context;
20import android.content.Intent;
21import android.graphics.Outline;
22import android.graphics.Rect;
23import android.util.AttributeSet;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.ImageView;
27import android.widget.LinearLayout;
28import android.widget.RelativeLayout;
29import android.widget.TextView;
30
31import com.android.systemui.R;
32import com.android.systemui.qs.QSPanel;
33import com.android.systemui.settings.BrightnessController;
34import com.android.systemui.settings.ToggleSlider;
35import com.android.systemui.statusbar.policy.UserInfoController;
36
37/**
38 * The view to manage the header area in the expanded status bar.
39 */
40public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener {
41
42    /**
43     * How much the header expansion gets rubberbanded while expanding the panel.
44     */
45    private static final float EXPANSION_RUBBERBAND_FACTOR = 0.35f;
46
47    private boolean mExpanded;
48    private boolean mOverscrolled;
49    private boolean mKeyguardShowing;
50
51    private View mBackground;
52    private ViewGroup mSystemIconsContainer;
53    private View mDateTime;
54    private View mKeyguardCarrierText;
55    private MultiUserSwitch mMultiUserSwitch;
56    private View mDate;
57    private View mStatusIcons;
58    private View mSignalCluster;
59    private View mSettingsButton;
60    private View mBrightnessContainer;
61    private View mEmergencyCallsOnly;
62    private TextView mChargingInfo;
63
64    private boolean mShowEmergencyCallsOnly;
65    private boolean mShowChargingInfo;
66    private boolean mKeyguardUserSwitcherShowing;
67
68    private int mCollapsedHeight;
69    private int mExpandedHeight;
70    private int mKeyguardHeight;
71
72    private int mKeyguardWidth = ViewGroup.LayoutParams.MATCH_PARENT;
73    private int mNormalWidth;
74    private int mPadding;
75    private int mMultiUserExpandedMargin;
76    private int mSystemIconsSwitcherHiddenExpandedMargin;
77
78    private ActivityStarter mActivityStarter;
79    private BrightnessController mBrightnessController;
80    private QSPanel mQSPanel;
81
82    private final Rect mClipBounds = new Rect();
83    private final Outline mOutline = new Outline();
84
85    public StatusBarHeaderView(Context context, AttributeSet attrs) {
86        super(context, attrs);
87    }
88
89    @Override
90    protected void onFinishInflate() {
91        super.onFinishInflate();
92        mBackground = findViewById(R.id.background);
93        mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
94        mDateTime = findViewById(R.id.datetime);
95        mKeyguardCarrierText = findViewById(R.id.keyguard_carrier_text);
96        mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
97        mDate = findViewById(R.id.date);
98        mSettingsButton = findViewById(R.id.settings_button);
99        mSettingsButton.setOnClickListener(this);
100        mBrightnessContainer = findViewById(R.id.brightness_container);
101        mBrightnessController = new BrightnessController(getContext(),
102                (ImageView) findViewById(R.id.brightness_icon),
103                (ToggleSlider) findViewById(R.id.brightness_slider));
104        mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only);
105        mChargingInfo = (TextView) findViewById(R.id.header_charging_info);
106        loadDimens();
107        updateVisibilities();
108        addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
109            @Override
110            public void onLayoutChange(View v, int left, int top, int right,
111                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
112                if ((right - left) != (oldRight - oldLeft)) {
113                    // width changed, update clipping
114                    setClipping(getHeight());
115                }
116            }
117        });
118    }
119
120    private void loadDimens() {
121        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
122        mExpandedHeight = getResources().getDimensionPixelSize(
123                R.dimen.status_bar_header_height_expanded);
124        mKeyguardHeight = getResources().getDimensionPixelSize(
125                R.dimen.status_bar_header_height_keyguard);
126        mNormalWidth = getLayoutParams().width;
127        mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding);
128        mMultiUserExpandedMargin =
129                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
130        mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
131                R.dimen.system_icons_switcher_hidden_expanded_margin);
132    }
133
134    public void setActivityStarter(ActivityStarter activityStarter) {
135        mActivityStarter = activityStarter;
136    }
137
138    public int getCollapsedHeight() {
139        return mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight;
140    }
141
142    public int getExpandedHeight() {
143        return mExpandedHeight;
144    }
145
146    public void setExpanded(boolean expanded, boolean overscrolled) {
147        boolean changed = expanded != mExpanded;
148        boolean overscrollChanged = overscrolled != mOverscrolled;
149        mExpanded = expanded;
150        mOverscrolled = overscrolled;
151        if (changed || overscrollChanged) {
152            updateHeights();
153            updateVisibilities();
154            updateSystemIconsLayoutParams();
155            updateBrightnessControllerState();
156            updateZTranslation();
157            updateClickTargets();
158            updateWidth();
159            updatePadding();
160            updateMultiUserSwitch();
161            if (mQSPanel != null) {
162                mQSPanel.setExpanded(expanded && !overscrolled);
163            }
164        }
165    }
166
167    private void updateHeights() {
168        boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
169        int height;
170        if (mExpanded) {
171            height = mExpandedHeight;
172        } else if (onKeyguardAndCollapsed) {
173            height = mKeyguardHeight;
174        } else {
175            height = mCollapsedHeight;
176        }
177        ViewGroup.LayoutParams lp = getLayoutParams();
178        if (lp.height != height) {
179            lp.height = height;
180            setLayoutParams(lp);
181        }
182        int systemIconsContainerHeight = onKeyguardAndCollapsed ? mKeyguardHeight : mCollapsedHeight;
183        lp = mSystemIconsContainer.getLayoutParams();
184        if (lp.height != systemIconsContainerHeight) {
185            lp.height = systemIconsContainerHeight;
186            mSystemIconsContainer.setLayoutParams(lp);
187        }
188        lp = mMultiUserSwitch.getLayoutParams();
189        if (lp.height != systemIconsContainerHeight) {
190            lp.height = systemIconsContainerHeight;
191            mMultiUserSwitch.setLayoutParams(lp);
192        }
193    }
194
195    private void updateWidth() {
196        int width = (mKeyguardShowing && !mExpanded) ? mKeyguardWidth : mNormalWidth;
197        ViewGroup.LayoutParams lp = getLayoutParams();
198        if (width != lp.width) {
199            lp.width = width;
200            setLayoutParams(lp);
201        }
202    }
203
204    private void updateVisibilities() {
205        boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
206        mBackground.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
207        mDateTime.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
208        mKeyguardCarrierText.setVisibility(onKeyguardAndCollapsed ? View.VISIBLE : View.GONE);
209        mDate.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
210        mSettingsButton.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.GONE);
211        mBrightnessContainer.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
212        if (mStatusIcons != null) {
213            mStatusIcons.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
214        }
215        if (mSignalCluster != null) {
216            mSignalCluster.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
217        }
218        mEmergencyCallsOnly.setVisibility(mExpanded && !mOverscrolled && mShowEmergencyCallsOnly
219                ? VISIBLE : GONE);
220        mChargingInfo.setVisibility(mExpanded && !mOverscrolled && mShowChargingInfo
221                && !mShowEmergencyCallsOnly ? VISIBLE : GONE);
222        mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing
223                ? VISIBLE : GONE);
224    }
225
226    private void updateSystemIconsLayoutParams() {
227        RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsContainer.getLayoutParams();
228        boolean systemIconsAboveClock = mExpanded && !mOverscrolled
229                && mShowChargingInfo && !mShowEmergencyCallsOnly;
230        lp.setMarginEnd(0);
231        if (systemIconsAboveClock) {
232            lp.addRule(ALIGN_PARENT_START);
233            lp.removeRule(START_OF);
234        } else {
235            lp.addRule(RelativeLayout.START_OF, mExpanded
236                    ? mSettingsButton.getId()
237                    : mMultiUserSwitch.getId());
238            lp.removeRule(ALIGN_PARENT_START);
239            if (mMultiUserSwitch.getVisibility() == GONE) {
240                lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin);
241            }
242        }
243        mSystemIconsContainer.setLayoutParams(lp);
244
245        RelativeLayout.LayoutParams clockLp = (LayoutParams) mDateTime.getLayoutParams();
246        if (systemIconsAboveClock) {
247            clockLp.addRule(BELOW, mChargingInfo.getId());
248        } else {
249            clockLp.addRule(BELOW, mEmergencyCallsOnly.getId());
250        }
251        mDateTime.setLayoutParams(clockLp);
252    }
253
254    private void updateBrightnessControllerState() {
255        if (mExpanded) {
256            mBrightnessController.registerCallbacks();
257        } else {
258            mBrightnessController.unregisterCallbacks();
259        }
260    }
261
262    private void updateClickTargets() {
263        mDateTime.setClickable(mExpanded);
264        mMultiUserSwitch.setClickable(mExpanded);
265    }
266
267    private void updateZTranslation() {
268
269        // If we are on the Keyguard, we need to set our z position to zero, so we don't get
270        // shadows.
271        if (mKeyguardShowing && !mExpanded) {
272            setZ(0);
273        } else {
274            setTranslationZ(0);
275        }
276    }
277
278    private void updatePadding() {
279        boolean padded = !mKeyguardShowing || mExpanded;
280        int padding = padded ? mPadding : 0;
281        setPaddingRelative(padding, 0, padding, 0);
282    }
283
284    private void updateMultiUserSwitch() {
285        int marginEnd = !mKeyguardShowing || mExpanded ? mMultiUserExpandedMargin : 0;
286        MarginLayoutParams lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams();
287        if (marginEnd != lp.getMarginEnd()) {
288            lp.setMarginEnd(marginEnd);
289            mMultiUserSwitch.setLayoutParams(lp);
290        }
291    }
292
293    public void setExpansion(float height) {
294        height = (height - mCollapsedHeight) * EXPANSION_RUBBERBAND_FACTOR + mCollapsedHeight;
295        if (height < mCollapsedHeight) {
296            height = mCollapsedHeight;
297        }
298        if (height > mExpandedHeight) {
299            height = mExpandedHeight;
300        }
301        setClipping(height);
302    }
303
304    private void setClipping(float height) {
305        mClipBounds.set(getPaddingLeft(), 0, getWidth() - getPaddingRight(), (int) height);
306        setClipBounds(mClipBounds);
307        mOutline.setRect(mClipBounds);
308        setOutline(mOutline);
309    }
310
311    public View getBackgroundView() {
312        return mBackground;
313    }
314
315    public void attachSystemIcons(LinearLayout systemIcons) {
316        mSystemIconsContainer.addView(systemIcons);
317        mStatusIcons = systemIcons.findViewById(R.id.statusIcons);
318        mSignalCluster = systemIcons.findViewById(R.id.signal_cluster);
319    }
320
321    public void onSystemIconsDetached() {
322        if (mStatusIcons != null) {
323            mStatusIcons.setVisibility(View.VISIBLE);
324        }
325        if (mSignalCluster != null) {
326            mSignalCluster.setVisibility(View.VISIBLE);
327        }
328        mStatusIcons = null;
329        mSignalCluster = null;
330    }
331
332    public void setKeyguardShowing(boolean keyguardShowing) {
333        mKeyguardShowing = keyguardShowing;
334        updateHeights();
335        updateWidth();
336        updateVisibilities();
337        updateZTranslation();
338        updatePadding();
339        updateMultiUserSwitch();
340    }
341
342    public void setUserInfoController(UserInfoController userInfoController) {
343        mMultiUserSwitch.setUserInfoController(userInfoController);
344    }
345
346    public void setOverlayParent(ViewGroup parent) {
347        mMultiUserSwitch.setOverlayParent(parent);
348    }
349
350    @Override
351    public void onClick(View v) {
352        if (v == mSettingsButton) {
353            startSettingsActivity();
354        }
355    }
356
357    private void startSettingsActivity() {
358        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
359    }
360
361    public void setQSPanel(QSPanel qsp) {
362        mQSPanel = qsp;
363        if (mQSPanel != null) {
364            mQSPanel.setCallback(mQsPanelCallback);
365        }
366    }
367
368    private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
369        @Override
370        public void onShowingDetail(boolean showingDetail) {
371            mBrightnessContainer.animate().alpha(showingDetail ? 0 : 1).withLayer().start();
372        }
373    };
374
375    @Override
376    public boolean shouldDelayChildPressedState() {
377        return true;
378    }
379
380    public void setShowEmergencyCallsOnly(boolean show) {
381        mShowEmergencyCallsOnly = show;
382        if (mExpanded) {
383            updateVisibilities();
384            updateSystemIconsLayoutParams();
385        }
386    }
387
388    public void setShowChargingInfo(boolean showChargingInfo) {
389        mShowChargingInfo = showChargingInfo;
390        if (mExpanded) {
391            updateVisibilities();
392            updateSystemIconsLayoutParams();
393        }
394    }
395
396    public void setChargingInfo(CharSequence chargingInfo) {
397        mChargingInfo.setText(chargingInfo);
398    }
399
400    public void setKeyguardUserSwitcherShowing(boolean showing) {
401        // STOPSHIP: NOT CALLED PROPERLY WHEN GOING TO FULL SHADE AND RETURNING!?!
402        mKeyguardUserSwitcherShowing = showing;
403        updateVisibilities();
404        updateSystemIconsLayoutParams();
405    }
406}
407