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