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 
17 package com.android.systemui.statusbar.phone;
18 
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.graphics.Canvas;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.ViewStub;
25 import android.view.WindowInsets;
26 import android.widget.FrameLayout;
27 import com.android.systemui.AutoReinflateContainer;
28 import com.android.systemui.R;
29 import com.android.systemui.qs.QSContainer;
30 import com.android.systemui.qs.customize.QSCustomizer;
31 
32 /**
33  * The container with notification stack scroller and quick settings inside.
34  */
35 public class NotificationsQuickSettingsContainer extends FrameLayout
36         implements ViewStub.OnInflateListener, AutoReinflateContainer.InflateListener {
37 
38 
39     private AutoReinflateContainer mQsContainer;
40     private View mUserSwitcher;
41     private View mStackScroller;
42     private View mKeyguardStatusBar;
43     private boolean mInflated;
44     private boolean mQsExpanded;
45     private boolean mCustomizerAnimating;
46 
47     private int mBottomPadding;
48     private int mStackScrollerMargin;
49 
NotificationsQuickSettingsContainer(Context context, AttributeSet attrs)50     public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) {
51         super(context, attrs);
52     }
53 
54     @Override
onFinishInflate()55     protected void onFinishInflate() {
56         super.onFinishInflate();
57         mQsContainer = (AutoReinflateContainer) findViewById(R.id.qs_auto_reinflate_container);
58         mQsContainer.addInflateListener(this);
59         mStackScroller = findViewById(R.id.notification_stack_scroller);
60         mStackScrollerMargin = ((LayoutParams) mStackScroller.getLayoutParams()).bottomMargin;
61         mKeyguardStatusBar = findViewById(R.id.keyguard_header);
62         ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher);
63         userSwitcher.setOnInflateListener(this);
64         mUserSwitcher = userSwitcher;
65     }
66 
67     @Override
onConfigurationChanged(Configuration newConfig)68     protected void onConfigurationChanged(Configuration newConfig) {
69         super.onConfigurationChanged(newConfig);
70         reloadWidth(mQsContainer);
71         reloadWidth(mStackScroller);
72     }
73 
reloadWidth(View view)74     private void reloadWidth(View view) {
75         LayoutParams params = (LayoutParams) view.getLayoutParams();
76         params.width = getContext().getResources().getDimensionPixelSize(
77                 R.dimen.notification_panel_width);
78         view.setLayoutParams(params);
79     }
80 
81     @Override
onApplyWindowInsets(WindowInsets insets)82     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
83         mBottomPadding = insets.getStableInsetBottom();
84         setPadding(0, 0, 0, mBottomPadding);
85         return insets;
86     }
87 
88     @Override
drawChild(Canvas canvas, View child, long drawingTime)89     protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
90         boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE;
91         boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE;
92 
93         final boolean qsBottom = mQsExpanded && !mCustomizerAnimating;
94         View stackQsTop = qsBottom ? mStackScroller : mQsContainer;
95         View stackQsBottom = !qsBottom ? mStackScroller : mQsContainer;
96         // Invert the order of the scroll view and user switcher such that the notifications receive
97         // touches first but the panel gets drawn above.
98         if (child == mQsContainer) {
99             return super.drawChild(canvas, userSwitcherVisible && statusBarVisible ? mUserSwitcher
100                     : statusBarVisible ? mKeyguardStatusBar
101                     : userSwitcherVisible ? mUserSwitcher
102                     : stackQsBottom, drawingTime);
103         } else if (child == mStackScroller) {
104             return super.drawChild(canvas,
105                     userSwitcherVisible && statusBarVisible ? mKeyguardStatusBar
106                     : statusBarVisible || userSwitcherVisible ? stackQsBottom
107                     : stackQsTop,
108                     drawingTime);
109         } else if (child == mUserSwitcher) {
110             return super.drawChild(canvas,
111                     userSwitcherVisible && statusBarVisible ? stackQsBottom
112                     : stackQsTop,
113                     drawingTime);
114         } else if (child == mKeyguardStatusBar) {
115             return super.drawChild(canvas,
116                     stackQsTop,
117                     drawingTime);
118         } else {
119             return super.drawChild(canvas, child, drawingTime);
120         }
121     }
122 
123     @Override
onInflate(ViewStub stub, View inflated)124     public void onInflate(ViewStub stub, View inflated) {
125         if (stub == mUserSwitcher) {
126             mUserSwitcher = inflated;
127             mInflated = true;
128         }
129     }
130 
131     @Override
onInflated(View v)132     public void onInflated(View v) {
133         QSCustomizer customizer = ((QSContainer) v).getCustomizer();
134         customizer.setContainer(this);
135     }
136 
setQsExpanded(boolean expanded)137     public void setQsExpanded(boolean expanded) {
138         if (mQsExpanded != expanded) {
139             mQsExpanded = expanded;
140             invalidate();
141         }
142     }
143 
setCustomizerAnimating(boolean isAnimating)144     public void setCustomizerAnimating(boolean isAnimating) {
145         if (mCustomizerAnimating != isAnimating) {
146             mCustomizerAnimating = isAnimating;
147             invalidate();
148         }
149     }
150 
setCustomizerShowing(boolean isShowing)151     public void setCustomizerShowing(boolean isShowing) {
152         if (isShowing) {
153             // Clear out bottom paddings/margins so the qs customization can be full height.
154             setPadding(0, 0, 0, 0);
155             setBottomMargin(mStackScroller, 0);
156         } else {
157             setPadding(0, 0, 0, mBottomPadding);
158             setBottomMargin(mStackScroller, mStackScrollerMargin);
159         }
160 
161     }
162 
setBottomMargin(View v, int bottomMargin)163     private void setBottomMargin(View v, int bottomMargin) {
164         LayoutParams params = (LayoutParams) v.getLayoutParams();
165         params.bottomMargin = bottomMargin;
166         v.setLayoutParams(params);
167     }
168 }
169