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