1d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi/* 2d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * 4d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * you may not use this file except in compliance with the License. 6d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * You may obtain a copy of the License at 7d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * 8d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * 10d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * Unless required by applicable law or agreed to in writing, software 11d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * See the License for the specific language governing permissions and 14d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * limitations under the License 15d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi */ 16d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi 17d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggipackage com.android.systemui.statusbar.phone; 18d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi 190ceef211875515c2a7531f9baeae46339e700f3aJason Monkimport android.app.Fragment; 20d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggiimport android.content.Context; 21bef6de8b3fafea4453e28ecd419561563fcae771Jason Monkimport android.content.res.Configuration; 22bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggiimport android.graphics.Canvas; 23185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chenimport android.support.annotation.DimenRes; 24d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggiimport android.util.AttributeSet; 25bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggiimport android.view.View; 26bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggiimport android.view.ViewStub; 277ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monkimport android.view.ViewStub.OnInflateListener; 28e070018b3e26371e1260229060d022808e43837eJorim Jaggiimport android.view.WindowInsets; 29d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggiimport android.widget.FrameLayout; 3046767b77c004a3541c614f8e21d6a871dd148e54Jason Monk 31bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggiimport com.android.systemui.R; 327ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monkimport com.android.systemui.SysUiServiceProvider; 330ceef211875515c2a7531f9baeae46339e700f3aJason Monkimport com.android.systemui.fragments.FragmentHostManager; 347ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monkimport com.android.systemui.fragments.FragmentHostManager.FragmentListener; 350ceef211875515c2a7531f9baeae46339e700f3aJason Monkimport com.android.systemui.plugins.qs.QS; 367ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monkimport com.android.systemui.statusbar.NotificationData.Entry; 375cf1d0589a0045ee5f01802975f394847e891215Selim Cinekimport com.android.systemui.statusbar.notification.AboveShelfObserver; 385cf1d0589a0045ee5f01802975f394847e891215Selim Cinekimport com.android.systemui.statusbar.stack.NotificationStackScrollLayout; 39bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi 40d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi/** 41d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi * The container with notification stack scroller and quick settings inside. 42d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi */ 43bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggipublic class NotificationsQuickSettingsContainer extends FrameLayout 445cf1d0589a0045ee5f01802975f394847e891215Selim Cinek implements OnInflateListener, FragmentListener, 455cf1d0589a0045ee5f01802975f394847e891215Selim Cinek AboveShelfObserver.HasViewAboveShelfChangedListener { 46bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi 470ceef211875515c2a7531f9baeae46339e700f3aJason Monk private FrameLayout mQsFrame; 48bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi private View mUserSwitcher; 495cf1d0589a0045ee5f01802975f394847e891215Selim Cinek private NotificationStackScrollLayout mStackScroller; 50bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi private View mKeyguardStatusBar; 51bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi private boolean mInflated; 52b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean mQsExpanded; 538b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk private boolean mCustomizerAnimating; 54d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi 55428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk private int mBottomPadding; 56428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk private int mStackScrollerMargin; 575cf1d0589a0045ee5f01802975f394847e891215Selim Cinek private boolean mHasViewsAboveShelf; 58428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk 59d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) { 60d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi super(context, attrs); 61d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi } 62d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi 63d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi @Override 64bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi protected void onFinishInflate() { 65bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi super.onFinishInflate(); 660ceef211875515c2a7531f9baeae46339e700f3aJason Monk mQsFrame = (FrameLayout) findViewById(R.id.qs_frame); 67bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi mStackScroller = findViewById(R.id.notification_stack_scroller); 68428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk mStackScrollerMargin = ((LayoutParams) mStackScroller.getLayoutParams()).bottomMargin; 69bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi mKeyguardStatusBar = findViewById(R.id.keyguard_header); 70bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher); 71bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi userSwitcher.setOnInflateListener(this); 72bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi mUserSwitcher = userSwitcher; 73bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi } 74bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi 75bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi @Override 760ceef211875515c2a7531f9baeae46339e700f3aJason Monk protected void onAttachedToWindow() { 770ceef211875515c2a7531f9baeae46339e700f3aJason Monk super.onAttachedToWindow(); 780ceef211875515c2a7531f9baeae46339e700f3aJason Monk FragmentHostManager.get(this).addTagListener(QS.TAG, this); 790ceef211875515c2a7531f9baeae46339e700f3aJason Monk } 800ceef211875515c2a7531f9baeae46339e700f3aJason Monk 810ceef211875515c2a7531f9baeae46339e700f3aJason Monk @Override 820ceef211875515c2a7531f9baeae46339e700f3aJason Monk protected void onDetachedFromWindow() { 830ceef211875515c2a7531f9baeae46339e700f3aJason Monk super.onDetachedFromWindow(); 840ceef211875515c2a7531f9baeae46339e700f3aJason Monk FragmentHostManager.get(this).removeTagListener(QS.TAG, this); 850ceef211875515c2a7531f9baeae46339e700f3aJason Monk } 860ceef211875515c2a7531f9baeae46339e700f3aJason Monk 870ceef211875515c2a7531f9baeae46339e700f3aJason Monk @Override 88bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk protected void onConfigurationChanged(Configuration newConfig) { 89bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk super.onConfigurationChanged(newConfig); 90185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen reloadWidth(mQsFrame, R.dimen.qs_panel_width); 91185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen reloadWidth(mStackScroller, R.dimen.notification_panel_width); 92bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk } 93bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk 94185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen /** 95185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen * Loads the given width resource and sets it on the given View. 96185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen */ 97185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen private void reloadWidth(View view, @DimenRes int width) { 98bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk LayoutParams params = (LayoutParams) view.getLayoutParams(); 99185b6f6483c9e9b81092f4280496b6c5842d1266Anthony Chen params.width = getResources().getDimensionPixelSize(width); 100bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk view.setLayoutParams(params); 101bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk } 102bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk 103bef6de8b3fafea4453e28ecd419561563fcae771Jason Monk @Override 104e070018b3e26371e1260229060d022808e43837eJorim Jaggi public WindowInsets onApplyWindowInsets(WindowInsets insets) { 105428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk mBottomPadding = insets.getStableInsetBottom(); 106428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk setPadding(0, 0, 0, mBottomPadding); 107e070018b3e26371e1260229060d022808e43837eJorim Jaggi return insets; 108d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi } 109bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi 110bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi @Override 111bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 112bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE; 113bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE; 114bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi 1155cf1d0589a0045ee5f01802975f394847e891215Selim Cinek final boolean qsBottom = mHasViewsAboveShelf; 1160ceef211875515c2a7531f9baeae46339e700f3aJason Monk View stackQsTop = qsBottom ? mStackScroller : mQsFrame; 1170ceef211875515c2a7531f9baeae46339e700f3aJason Monk View stackQsBottom = !qsBottom ? mStackScroller : mQsFrame; 118bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi // Invert the order of the scroll view and user switcher such that the notifications receive 119bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi // touches first but the panel gets drawn above. 1200ceef211875515c2a7531f9baeae46339e700f3aJason Monk if (child == mQsFrame) { 121b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return super.drawChild(canvas, userSwitcherVisible && statusBarVisible ? mUserSwitcher 122bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi : statusBarVisible ? mKeyguardStatusBar 123bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi : userSwitcherVisible ? mUserSwitcher 124b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek : stackQsBottom, drawingTime); 125b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } else if (child == mStackScroller) { 126b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return super.drawChild(canvas, 127b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek userSwitcherVisible && statusBarVisible ? mKeyguardStatusBar 128b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek : statusBarVisible || userSwitcherVisible ? stackQsBottom 129b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek : stackQsTop, 130bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi drawingTime); 131bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi } else if (child == mUserSwitcher) { 132bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi return super.drawChild(canvas, 133b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek userSwitcherVisible && statusBarVisible ? stackQsBottom 134b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek : stackQsTop, 135bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi drawingTime); 136bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi } else if (child == mKeyguardStatusBar) { 137bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi return super.drawChild(canvas, 138b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek stackQsTop, 139bf1899e64c0fbb0fa211d883134012299fe79f41Jorim Jaggi drawingTime); 14016ac3774e394d50600079697ea867a3c847ebd95Jason Monk } else { 141bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi return super.drawChild(canvas, child, drawingTime); 142bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi } 143bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi } 144bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi 145bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi @Override 146bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi public void onInflate(ViewStub stub, View inflated) { 147bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi if (stub == mUserSwitcher) { 148bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi mUserSwitcher = inflated; 149bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi mInflated = true; 150bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi } 151bc976e3f4c79a8565ec625564c92d316825f26a7Jorim Jaggi } 152b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 1538b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk @Override 1540ceef211875515c2a7531f9baeae46339e700f3aJason Monk public void onFragmentViewCreated(String tag, Fragment fragment) { 1550ceef211875515c2a7531f9baeae46339e700f3aJason Monk QS container = (QS) fragment; 15646767b77c004a3541c614f8e21d6a871dd148e54Jason Monk container.setContainer(this); 1578b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 1588b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 159b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setQsExpanded(boolean expanded) { 160b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (mQsExpanded != expanded) { 161b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mQsExpanded = expanded; 162b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek invalidate(); 163b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 164b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 1658b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 1668b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk public void setCustomizerAnimating(boolean isAnimating) { 1678b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk if (mCustomizerAnimating != isAnimating) { 1688b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mCustomizerAnimating = isAnimating; 1698b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk invalidate(); 1708b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 1718b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 172428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk 173428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk public void setCustomizerShowing(boolean isShowing) { 174428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk if (isShowing) { 175428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk // Clear out bottom paddings/margins so the qs customization can be full height. 176428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk setPadding(0, 0, 0, 0); 177428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk setBottomMargin(mStackScroller, 0); 178428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk } else { 179428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk setPadding(0, 0, 0, mBottomPadding); 180428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk setBottomMargin(mStackScroller, mStackScrollerMargin); 181428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk } 1825cf1d0589a0045ee5f01802975f394847e891215Selim Cinek mStackScroller.setQsCustomizerShowing(isShowing); 183428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk } 184428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk 185428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk private void setBottomMargin(View v, int bottomMargin) { 186428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk LayoutParams params = (LayoutParams) v.getLayoutParams(); 187428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk params.bottomMargin = bottomMargin; 188428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk v.setLayoutParams(params); 189428914d0f07f4a0d5b55c4de7ec30708505bd21fJason Monk } 1907ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monk 1917ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monk @Override 1925cf1d0589a0045ee5f01802975f394847e891215Selim Cinek public void onHasViewsAboveShelfChanged(boolean hasViewsAboveShelf) { 1935cf1d0589a0045ee5f01802975f394847e891215Selim Cinek mHasViewsAboveShelf = hasViewsAboveShelf; 1947ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monk invalidate(); 1957ebba0be6c76abc2f030d0e23568631ffd16b819Jason Monk } 196d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi} 197