blob: be8a8fd2615086943c933a495bda03bc2bab0e61 [file] [log] [blame]
Jorim Jaggi8bc983e2014-12-10 17:45:50 +01001/*
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.qs;
18
Amin Shaikhf09450b2018-04-06 17:32:45 -040019import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
Bill Linbe9d20a2018-06-07 16:25:46 +080020import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
Amin Shaikhf09450b2018-04-06 17:32:45 -040021
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010022import android.content.Context;
Jason Monk231b0522018-01-04 10:49:55 -050023import android.content.res.Configuration;
Jason Monk8b9d67f2016-03-02 08:59:08 -050024import android.graphics.Point;
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010025import android.util.AttributeSet;
Jason Monke1be3422016-02-09 10:51:40 -050026import android.view.View;
Jason Monk0ceef212016-11-02 14:05:23 -040027import android.widget.FrameLayout;
Jason Monk46767b72016-08-18 10:58:04 -040028
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010029import com.android.systemui.R;
Jason Monk8b9d67f2016-03-02 08:59:08 -050030import com.android.systemui.qs.customize.QSCustomizer;
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010031
32/**
Jason Monke1be3422016-02-09 10:51:40 -050033 * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010034 */
Jason Monk0ceef212016-11-02 14:05:23 -040035public class QSContainerImpl extends FrameLayout {
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010036
Jason Monk8b9d67f2016-03-02 08:59:08 -050037 private final Point mSizePoint = new Point();
38
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010039 private int mHeightOverride = -1;
Amin Shaikhbc1a4e82018-04-16 12:14:35 -040040 private QSPanel mQSPanel;
Jason Monk0ceef212016-11-02 14:05:23 -040041 private View mQSDetail;
Amin Shaikh50d2d1e2018-04-25 14:48:13 -040042 private QuickStatusBarHeader mHeader;
Amin Shaikhbc1a4e82018-04-16 12:14:35 -040043 private float mQsExpansion;
Jason Monk8b9d67f2016-03-02 08:59:08 -050044 private QSCustomizer mQSCustomizer;
Anthony Chen54daefe2017-04-07 17:19:54 -070045 private View mQSFooter;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000046
Evan Laird39254d42018-01-18 16:05:30 -050047 private View mBackground;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000048 private View mBackgroundGradient;
49 private View mStatusBarBackground;
50
Evan Laird39254d42018-01-18 16:05:30 -050051 private int mSideMargins;
Amin Shaikhf09450b2018-04-06 17:32:45 -040052 private boolean mQsDisabled;
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010053
Jason Monk46767b72016-08-18 10:58:04 -040054 public QSContainerImpl(Context context, AttributeSet attrs) {
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010055 super(context, attrs);
56 }
57
58 @Override
59 protected void onFinishInflate() {
60 super.onFinishInflate();
Jason Monk0ceef212016-11-02 14:05:23 -040061 mQSPanel = findViewById(R.id.quick_settings_panel);
62 mQSDetail = findViewById(R.id.qs_detail);
63 mHeader = findViewById(R.id.header);
Jason Monke5b770e2017-03-03 21:49:29 -050064 mQSCustomizer = findViewById(R.id.qs_customize);
65 mQSFooter = findViewById(R.id.qs_footer);
Evan Laird39254d42018-01-18 16:05:30 -050066 mBackground = findViewById(R.id.quick_settings_background);
Rohan Shahcc3d1d82018-03-30 21:24:17 +000067 mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background);
68 mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
Evan Laird39254d42018-01-18 16:05:30 -050069 mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
Jason Monk7b3d4e42017-05-30 12:47:10 -040070
Jason Monk7b3d4e42017-05-30 12:47:10 -040071 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
Evan Laird39254d42018-01-18 16:05:30 -050072 setMargins();
Jason Monk7b3d4e42017-05-30 12:47:10 -040073 }
74
75 @Override
Rohan Shahcc3d1d82018-03-30 21:24:17 +000076 protected void onConfigurationChanged(Configuration newConfig) {
77 super.onConfigurationChanged(newConfig);
Bill Linbe9d20a2018-06-07 16:25:46 +080078 setBackgroundGradientVisibility(newConfig);
Rohan Shahcc3d1d82018-03-30 21:24:17 +000079 updateResources();
Amin Shaikh375b8dd2018-04-10 10:50:22 -040080 mSizePoint.set(0, 0); // Will be retrieved on next measure pass.
Rohan Shahcc3d1d82018-03-30 21:24:17 +000081 }
82
83 @Override
Jason Monk7b3d4e42017-05-30 12:47:10 -040084 public boolean performClick() {
85 // Want to receive clicks so missing QQS tiles doesn't cause collapse, but
86 // don't want to do anything with them.
87 return true;
Jason Monk8b9d67f2016-03-02 08:59:08 -050088 }
89
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010090 @Override
Jason Monk83e431f2016-02-19 19:32:13 -050091 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Fabian Kozynski712ae392018-09-12 09:11:16 -040092 // QSPanel will show as many rows as it can (up to TileLayout.MAX_ROWS) such that the
93 // bottom and footer are inside the screen.
94 Configuration config = getResources().getConfiguration();
95 boolean navBelow = config.smallestScreenWidthDp >= 600
96 || config.orientation != Configuration.ORIENTATION_LANDSCAPE;
97 MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanel.getLayoutParams();
98
99 // The footer is pinned to the bottom of QSPanel (same bottoms), therefore we don't need to
100 // subtract its height. We do not care if the collapsed notifications fit in the screen.
101 int maxQs = getDisplayHeight() - layoutParams.topMargin - layoutParams.bottomMargin
102 - getPaddingBottom();
103 if (navBelow) {
104 maxQs -= getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
105 }
Fabian Kozynski72cd84a92019-04-15 14:09:43 -0400106 // Measure with EXACTLY. That way, PagedTileLayout will only use excess height and will be
107 // measured last, after other views and padding is accounted for.
108 mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.EXACTLY));
Jason Monk6573ef22016-04-06 12:37:18 -0400109 int width = mQSPanel.getMeasuredWidth();
Jason Monke5b770e2017-03-03 21:49:29 -0500110 int height = layoutParams.topMargin + layoutParams.bottomMargin
Fabian Kozynski712ae392018-09-12 09:11:16 -0400111 + mQSPanel.getMeasuredHeight() + getPaddingBottom();
Jason Monk6573ef22016-04-06 12:37:18 -0400112 super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
113 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
Jason Monk0ceef212016-11-02 14:05:23 -0400114 // QSCustomizer will always be the height of the screen, but do this after
115 // other measuring to avoid changing the height of the QS.
Jason Monk8b9d67f2016-03-02 08:59:08 -0500116 mQSCustomizer.measure(widthMeasureSpec,
Amin Shaikh375b8dd2018-04-10 10:50:22 -0400117 MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY));
Jason Monk83e431f2016-02-19 19:32:13 -0500118 }
119
Fabian Kozynski0b7d6172019-08-08 15:53:34 -0400120
121 @Override
122 protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
123 int parentHeightMeasureSpec, int heightUsed) {
124 // Do not measure QSPanel again when doing super.onMeasure.
125 // This prevents the pages in PagedTileLayout to be remeasured with a different (incorrect)
126 // size to the one used for determining the number of rows and then the number of pages.
127 if (child != mQSPanel) {
128 super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
129 parentHeightMeasureSpec, heightUsed);
130 }
131 }
132
Jason Monk83e431f2016-02-19 19:32:13 -0500133 @Override
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100134 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
135 super.onLayout(changed, left, top, right, bottom);
Jason Monk4de5d3c2017-05-24 14:57:10 -0400136 updateExpansion();
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100137 }
138
Amin Shaikhf09450b2018-04-06 17:32:45 -0400139 public void disable(int state1, int state2, boolean animate) {
140 final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
141 if (disabled == mQsDisabled) return;
142 mQsDisabled = disabled;
Bill Linbe9d20a2018-06-07 16:25:46 +0800143 setBackgroundGradientVisibility(getResources().getConfiguration());
Amin Shaikhe04505e2018-04-18 10:45:13 -0400144 mBackground.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
Amin Shaikhf09450b2018-04-06 17:32:45 -0400145 }
146
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000147 private void updateResources() {
148 LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
149 layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
150 com.android.internal.R.dimen.quick_qs_offset_height);
151
152 mQSPanel.setLayoutParams(layoutParams);
153 }
154
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100155 /**
156 * Overrides the height of this view (post-layout), so that the content is clipped to that
157 * height and the background is set to that height.
158 *
159 * @param heightOverride the overridden height
160 */
161 public void setHeightOverride(int heightOverride) {
162 mHeightOverride = heightOverride;
Jason Monk4de5d3c2017-05-24 14:57:10 -0400163 updateExpansion();
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100164 }
165
Jason Monk4de5d3c2017-05-24 14:57:10 -0400166 public void updateExpansion() {
Muyuan Li4fe4a402016-03-30 16:50:11 -0700167 int height = calculateContainerHeight();
Jason Monk232ac2b2017-06-02 12:50:24 -0400168 setBottom(getTop() + height);
Jason Monk377e7ad2016-02-16 14:03:21 -0500169 mQSDetail.setBottom(getTop() + height);
Jason Monke5b770e2017-03-03 21:49:29 -0500170 // Pin QS Footer to the bottom of the panel.
171 mQSFooter.setTranslationY(height - mQSFooter.getHeight());
Evan Laird39254d42018-01-18 16:05:30 -0500172 mBackground.setTop(mQSPanel.getTop());
173 mBackground.setBottom(height);
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100174 }
Jason Monke1be3422016-02-09 10:51:40 -0500175
Muyuan Li4fe4a402016-03-30 16:50:11 -0700176 protected int calculateContainerHeight() {
177 int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
178 return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
Jason Monk4de5d3c2017-05-24 14:57:10 -0400179 : Math.round(mQsExpansion * (heightOverride - mHeader.getHeight()))
Jason Monk0ceef212016-11-02 14:05:23 -0400180 + mHeader.getHeight();
Muyuan Li4fe4a402016-03-30 16:50:11 -0700181 }
182
Bill Linbe9d20a2018-06-07 16:25:46 +0800183 private void setBackgroundGradientVisibility(Configuration newConfig) {
184 if (newConfig.orientation == ORIENTATION_LANDSCAPE) {
185 mBackgroundGradient.setVisibility(View.INVISIBLE);
186 mStatusBarBackground.setVisibility(View.INVISIBLE);
187 } else {
188 mBackgroundGradient.setVisibility(mQsDisabled ? View.INVISIBLE : View.VISIBLE);
189 mStatusBarBackground.setVisibility(View.VISIBLE);
190 }
191 }
192
Jason Monk0ceef212016-11-02 14:05:23 -0400193 public void setExpansion(float expansion) {
Jason Monke1be3422016-02-09 10:51:40 -0500194 mQsExpansion = expansion;
Jason Monk4de5d3c2017-05-24 14:57:10 -0400195 updateExpansion();
196 }
Evan Laird39254d42018-01-18 16:05:30 -0500197
198 private void setMargins() {
199 setMargins(mQSDetail);
200 setMargins(mBackground);
201 setMargins(mQSFooter);
Amin Shaikhbc1a4e82018-04-16 12:14:35 -0400202 mQSPanel.setMargins(mSideMargins);
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400203 mHeader.setMargins(mSideMargins);
Evan Laird39254d42018-01-18 16:05:30 -0500204 }
205
206 private void setMargins(View view) {
207 FrameLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();
208 lp.rightMargin = mSideMargins;
209 lp.leftMargin = mSideMargins;
210 }
Amin Shaikh375b8dd2018-04-10 10:50:22 -0400211
212 private int getDisplayHeight() {
213 if (mSizePoint.y == 0) {
214 getDisplay().getRealSize(mSizePoint);
215 }
216 return mSizePoint.y;
217 }
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100218}