blob: 6b0d592a4d01606a0914f2271eb56c6fe7e49fe4 [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
19import android.content.Context;
Jason Monk231b0522018-01-04 10:49:55 -050020import android.content.res.Configuration;
Jason Monk8a514cb2018-01-15 15:24:09 -050021import android.graphics.Canvas;
22import android.graphics.Path;
Jason Monk8b9d67f2016-03-02 08:59:08 -050023import android.graphics.Point;
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010024import android.util.AttributeSet;
Jason Monke1be3422016-02-09 10:51:40 -050025import android.view.View;
Jason Monk0ceef212016-11-02 14:05:23 -040026import android.widget.FrameLayout;
Jason Monk46767b72016-08-18 10:58:04 -040027
Jason Monk8a514cb2018-01-15 15:24:09 -050028import com.android.settingslib.Utils;
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;
Jason Monk8a514cb2018-01-15 15:24:09 -050031import com.android.systemui.statusbar.ExpandableOutlineView;
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010032
33/**
Jason Monke1be3422016-02-09 10:51:40 -050034 * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010035 */
Jason Monk0ceef212016-11-02 14:05:23 -040036public class QSContainerImpl extends FrameLayout {
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010037
Jason Monk8b9d67f2016-03-02 08:59:08 -050038 private final Point mSizePoint = new Point();
Jason Monk8a514cb2018-01-15 15:24:09 -050039 private final Path mClipPath = new Path();
Jason Monk8b9d67f2016-03-02 08:59:08 -050040
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010041 private int mHeightOverride = -1;
Jason Monk0ceef212016-11-02 14:05:23 -040042 protected View mQSPanel;
43 private View mQSDetail;
44 protected View mHeader;
Muyuan Li4fe4a402016-03-30 16:50:11 -070045 protected float mQsExpansion;
Jason Monk8b9d67f2016-03-02 08:59:08 -050046 private QSCustomizer mQSCustomizer;
Anthony Chen54daefe2017-04-07 17:19:54 -070047 private View mQSFooter;
Evan Laird39254d42018-01-18 16:05:30 -050048 private View mBackground;
Jason Monk8a514cb2018-01-15 15:24:09 -050049 private float mRadius;
Evan Laird39254d42018-01-18 16:05:30 -050050 private int mSideMargins;
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010051
Jason Monk46767b72016-08-18 10:58:04 -040052 public QSContainerImpl(Context context, AttributeSet attrs) {
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010053 super(context, attrs);
54 }
55
56 @Override
57 protected void onFinishInflate() {
58 super.onFinishInflate();
Jason Monk0ceef212016-11-02 14:05:23 -040059 mQSPanel = findViewById(R.id.quick_settings_panel);
60 mQSDetail = findViewById(R.id.qs_detail);
61 mHeader = findViewById(R.id.header);
Jason Monke5b770e2017-03-03 21:49:29 -050062 mQSCustomizer = findViewById(R.id.qs_customize);
63 mQSFooter = findViewById(R.id.qs_footer);
Evan Laird39254d42018-01-18 16:05:30 -050064 mBackground = findViewById(R.id.quick_settings_background);
Jason Monk8a514cb2018-01-15 15:24:09 -050065 mRadius = getResources().getDimensionPixelSize(
66 Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
Evan Laird39254d42018-01-18 16:05:30 -050067 mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
Jason Monk7b3d4e42017-05-30 12:47:10 -040068
69 setClickable(true);
70 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
Evan Laird39254d42018-01-18 16:05:30 -050071 setMargins();
Jason Monk7b3d4e42017-05-30 12:47:10 -040072 }
73
74 @Override
75 public boolean performClick() {
76 // Want to receive clicks so missing QQS tiles doesn't cause collapse, but
77 // don't want to do anything with them.
78 return true;
Jason Monk8b9d67f2016-03-02 08:59:08 -050079 }
80
Jorim Jaggi8bc983e2014-12-10 17:45:50 +010081 @Override
Jason Monk83e431f2016-02-19 19:32:13 -050082 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Jason Monk231b0522018-01-04 10:49:55 -050083 getDisplay().getRealSize(mSizePoint);
84
Jason Monk83e431f2016-02-19 19:32:13 -050085 // Since we control our own bottom, be whatever size we want.
86 // Otherwise the QSPanel ends up with 0 height when the window is only the
87 // size of the status bar.
Jason Monk231b0522018-01-04 10:49:55 -050088 Configuration config = getResources().getConfiguration();
89 boolean navBelow = config.smallestScreenWidthDp >= 600
90 || config.orientation != Configuration.ORIENTATION_LANDSCAPE;
91 MarginLayoutParams params = (MarginLayoutParams) mQSPanel.getLayoutParams();
92 int maxQs = mSizePoint.y - params.topMargin - params.bottomMargin - getPaddingBottom()
93 - getResources().getDimensionPixelSize(R.dimen.qs_notif_collapsed_space);
94 if (navBelow) {
95 maxQs -= getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
96 }
97 mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.AT_MOST));
98
Jason Monk6573ef22016-04-06 12:37:18 -040099 int width = mQSPanel.getMeasuredWidth();
Jason Monke5b770e2017-03-03 21:49:29 -0500100 LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
101 int height = layoutParams.topMargin + layoutParams.bottomMargin
Jason Monk6573ef22016-04-06 12:37:18 -0400102 + mQSPanel.getMeasuredHeight();
103 super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
104 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
Jason Monk8b9d67f2016-03-02 08:59:08 -0500105
Jason Monk0ceef212016-11-02 14:05:23 -0400106 // QSCustomizer will always be the height of the screen, but do this after
107 // other measuring to avoid changing the height of the QS.
Jason Monk8b9d67f2016-03-02 08:59:08 -0500108 mQSCustomizer.measure(widthMeasureSpec,
109 MeasureSpec.makeMeasureSpec(mSizePoint.y, MeasureSpec.EXACTLY));
Jason Monk83e431f2016-02-19 19:32:13 -0500110 }
111
112 @Override
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100113 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
114 super.onLayout(changed, left, top, right, bottom);
Jason Monk4de5d3c2017-05-24 14:57:10 -0400115 updateExpansion();
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100116 }
117
Jason Monk8a514cb2018-01-15 15:24:09 -0500118 @Override
119 protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
120 boolean ret;
121 canvas.save();
122 if (child != mQSCustomizer) {
123 canvas.clipPath(mClipPath);
124 }
125 ret = super.drawChild(canvas, child, drawingTime);
126 canvas.restore();
127 return ret;
128 }
129
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100130 /**
131 * Overrides the height of this view (post-layout), so that the content is clipped to that
132 * height and the background is set to that height.
133 *
134 * @param heightOverride the overridden height
135 */
136 public void setHeightOverride(int heightOverride) {
137 mHeightOverride = heightOverride;
Jason Monk4de5d3c2017-05-24 14:57:10 -0400138 updateExpansion();
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100139 }
140
Jason Monk4de5d3c2017-05-24 14:57:10 -0400141 public void updateExpansion() {
Muyuan Li4fe4a402016-03-30 16:50:11 -0700142 int height = calculateContainerHeight();
Jason Monk232ac2b2017-06-02 12:50:24 -0400143 setBottom(getTop() + height);
Jason Monk377e7ad2016-02-16 14:03:21 -0500144 mQSDetail.setBottom(getTop() + height);
Jason Monke5b770e2017-03-03 21:49:29 -0500145 // Pin QS Footer to the bottom of the panel.
146 mQSFooter.setTranslationY(height - mQSFooter.getHeight());
Evan Laird39254d42018-01-18 16:05:30 -0500147 mBackground.setTop(mQSPanel.getTop());
148 mBackground.setBottom(height);
Jason Monk8a514cb2018-01-15 15:24:09 -0500149
150 ExpandableOutlineView.getRoundedRectPath(0, 0, getWidth(), height, mRadius,
151 mRadius,
152 mClipPath);
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100153 }
Jason Monke1be3422016-02-09 10:51:40 -0500154
Muyuan Li4fe4a402016-03-30 16:50:11 -0700155 protected int calculateContainerHeight() {
156 int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
157 return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
Jason Monk4de5d3c2017-05-24 14:57:10 -0400158 : Math.round(mQsExpansion * (heightOverride - mHeader.getHeight()))
Jason Monk0ceef212016-11-02 14:05:23 -0400159 + mHeader.getHeight();
Muyuan Li4fe4a402016-03-30 16:50:11 -0700160 }
161
Jason Monk0ceef212016-11-02 14:05:23 -0400162 public void setExpansion(float expansion) {
Jason Monke1be3422016-02-09 10:51:40 -0500163 mQsExpansion = expansion;
Jason Monk4de5d3c2017-05-24 14:57:10 -0400164 updateExpansion();
165 }
Evan Laird39254d42018-01-18 16:05:30 -0500166
167 private void setMargins() {
168 setMargins(mQSDetail);
169 setMargins(mBackground);
170 setMargins(mQSFooter);
171 setMargins(mQSPanel);
172 setMargins(mHeader);
173 setMargins(mQSCustomizer);
174 }
175
176 private void setMargins(View view) {
177 FrameLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();
178 lp.rightMargin = mSideMargins;
179 lp.leftMargin = mSideMargins;
180 }
Jorim Jaggi8bc983e2014-12-10 17:45:50 +0100181}