• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app.Fragment;
20 import android.content.Context;
21 import android.content.res.Configuration;
22 import android.graphics.Canvas;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.view.ViewStub;
26 import android.view.ViewStub.OnInflateListener;
27 import android.view.WindowInsets;
28 import android.widget.FrameLayout;
29 
30 import androidx.annotation.DimenRes;
31 
32 import com.android.systemui.R;
33 import com.android.systemui.fragments.FragmentHostManager;
34 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
35 import com.android.systemui.plugins.qs.QS;
36 import com.android.systemui.statusbar.notification.AboveShelfObserver;
37 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
38 
39 /**
40  * The container with notification stack scroller and quick settings inside.
41  */
42 public class NotificationsQuickSettingsContainer extends FrameLayout
43         implements OnInflateListener, FragmentListener,
44         AboveShelfObserver.HasViewAboveShelfChangedListener {
45 
46     private FrameLayout mQsFrame;
47     private View mUserSwitcher;
48     private NotificationStackScrollLayout mStackScroller;
49     private View mKeyguardStatusBar;
50     private boolean mInflated;
51     private boolean mQsExpanded;
52     private boolean mCustomizerAnimating;
53 
54     private int mBottomPadding;
55     private int mStackScrollerMargin;
56     private boolean mHasViewsAboveShelf;
57 
NotificationsQuickSettingsContainer(Context context, AttributeSet attrs)58     public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) {
59         super(context, attrs);
60     }
61 
62     @Override
onFinishInflate()63     protected void onFinishInflate() {
64         super.onFinishInflate();
65         mQsFrame = (FrameLayout) findViewById(R.id.qs_frame);
66         mStackScroller = findViewById(R.id.notification_stack_scroller);
67         mStackScrollerMargin = ((LayoutParams) mStackScroller.getLayoutParams()).bottomMargin;
68         mKeyguardStatusBar = findViewById(R.id.keyguard_header);
69         ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher);
70         userSwitcher.setOnInflateListener(this);
71         mUserSwitcher = userSwitcher;
72     }
73 
74     @Override
onAttachedToWindow()75     protected void onAttachedToWindow() {
76         super.onAttachedToWindow();
77         FragmentHostManager.get(this).addTagListener(QS.TAG, this);
78     }
79 
80     @Override
onDetachedFromWindow()81     protected void onDetachedFromWindow() {
82         super.onDetachedFromWindow();
83         FragmentHostManager.get(this).removeTagListener(QS.TAG, this);
84     }
85 
86     @Override
onConfigurationChanged(Configuration newConfig)87     protected void onConfigurationChanged(Configuration newConfig) {
88         super.onConfigurationChanged(newConfig);
89         reloadWidth(mQsFrame, R.dimen.qs_panel_width);
90         reloadWidth(mStackScroller, R.dimen.notification_panel_width);
91     }
92 
93     /**
94      * Loads the given width resource and sets it on the given View.
95      */
reloadWidth(View view, @DimenRes int width)96     private void reloadWidth(View view, @DimenRes int width) {
97         LayoutParams params = (LayoutParams) view.getLayoutParams();
98         params.width = getResources().getDimensionPixelSize(width);
99         view.setLayoutParams(params);
100     }
101 
102     @Override
onApplyWindowInsets(WindowInsets insets)103     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
104         mBottomPadding = insets.getStableInsetBottom();
105         setPadding(0, 0, 0, mBottomPadding);
106         return insets;
107     }
108 
109     @Override
drawChild(Canvas canvas, View child, long drawingTime)110     protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
111         boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE;
112         boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE;
113 
114         final boolean qsBottom = mHasViewsAboveShelf;
115         View stackQsTop = qsBottom ? mStackScroller : mQsFrame;
116         View stackQsBottom = !qsBottom ? mStackScroller : mQsFrame;
117         // Invert the order of the scroll view and user switcher such that the notifications receive
118         // touches first but the panel gets drawn above.
119         if (child == mQsFrame) {
120             return super.drawChild(canvas, userSwitcherVisible && statusBarVisible ? mUserSwitcher
121                     : statusBarVisible ? mKeyguardStatusBar
122                     : userSwitcherVisible ? mUserSwitcher
123                     : stackQsBottom, drawingTime);
124         } else if (child == mStackScroller) {
125             return super.drawChild(canvas,
126                     userSwitcherVisible && statusBarVisible ? mKeyguardStatusBar
127                     : statusBarVisible || userSwitcherVisible ? stackQsBottom
128                     : stackQsTop,
129                     drawingTime);
130         } else if (child == mUserSwitcher) {
131             return super.drawChild(canvas,
132                     userSwitcherVisible && statusBarVisible ? stackQsBottom
133                     : stackQsTop,
134                     drawingTime);
135         } else if (child == mKeyguardStatusBar) {
136             return super.drawChild(canvas,
137                     stackQsTop,
138                     drawingTime);
139         } else {
140             return super.drawChild(canvas, child, drawingTime);
141         }
142     }
143 
144     @Override
onInflate(ViewStub stub, View inflated)145     public void onInflate(ViewStub stub, View inflated) {
146         if (stub == mUserSwitcher) {
147             mUserSwitcher = inflated;
148             mInflated = true;
149         }
150     }
151 
152     @Override
onFragmentViewCreated(String tag, Fragment fragment)153     public void onFragmentViewCreated(String tag, Fragment fragment) {
154         QS container = (QS) fragment;
155         container.setContainer(this);
156     }
157 
setQsExpanded(boolean expanded)158     public void setQsExpanded(boolean expanded) {
159         if (mQsExpanded != expanded) {
160             mQsExpanded = expanded;
161             invalidate();
162         }
163     }
164 
setCustomizerAnimating(boolean isAnimating)165     public void setCustomizerAnimating(boolean isAnimating) {
166         if (mCustomizerAnimating != isAnimating) {
167             mCustomizerAnimating = isAnimating;
168             invalidate();
169         }
170     }
171 
setCustomizerShowing(boolean isShowing)172     public void setCustomizerShowing(boolean isShowing) {
173         if (isShowing) {
174             // Clear out bottom paddings/margins so the qs customization can be full height.
175             setPadding(0, 0, 0, 0);
176             setBottomMargin(mStackScroller, 0);
177         } else {
178             setPadding(0, 0, 0, mBottomPadding);
179             setBottomMargin(mStackScroller, mStackScrollerMargin);
180         }
181         mStackScroller.setQsCustomizerShowing(isShowing);
182     }
183 
setBottomMargin(View v, int bottomMargin)184     private void setBottomMargin(View v, int bottomMargin) {
185         LayoutParams params = (LayoutParams) v.getLayoutParams();
186         params.bottomMargin = bottomMargin;
187         v.setLayoutParams(params);
188     }
189 
190     @Override
onHasViewsAboveShelfChanged(boolean hasViewsAboveShelf)191     public void onHasViewsAboveShelfChanged(boolean hasViewsAboveShelf) {
192         mHasViewsAboveShelf = hasViewsAboveShelf;
193         invalidate();
194     }
195 }
196