NotificationPanelView.java revision 0d74eeb9ec7ffe30d5c825bf7a3af96a53e2683d
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Copyright (C) 2012 The Android Open Source Project
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Licensed under the Apache License, Version 2.0 (the "License");
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * you may not use this file except in compliance with the License.
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * You may obtain a copy of the License at
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *      http://www.apache.org/licenses/LICENSE-2.0
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Unless required by applicable law or agreed to in writing, software
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * distributed under the License is distributed on an "AS IS" BASIS,
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * See the License for the specific language governing permissions and
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * limitations under the License.
15de7fb8413b13651fd85b7125d08b3c9ac2816d9dDaniel Dunbar */
16c4a1dea2dc56bd1357ec91b829a0b9e68229a13eDaniel Dunbar
17de7fb8413b13651fd85b7125d08b3c9ac2816d9dDaniel Dunbarpackage com.android.systemui.statusbar.phone;
18e91593ef084479340582b2ba177b44be50a717b7Daniel Dunbar
195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport android.animation.Animator;
204e533287e6a9adac78c9ac370612581aad9b8c5eAnders Carlssonimport android.animation.AnimatorListenerAdapter;
21d9e9ede6b1703849da739629904dad197306e527Devang Patelimport android.animation.ValueAnimator;
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport android.content.Context;
2345c25ba11cbf8c9a461def5b03f6ee9481e06769Daniel Dunbarimport android.util.AttributeSet;
2445c25ba11cbf8c9a461def5b03f6ee9481e06769Daniel Dunbarimport android.view.MotionEvent;
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport android.view.VelocityTracker;
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport android.view.View;
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerimport android.view.ViewGroup;
28057afddf0fab91d979d6a750667d56a345225c96Devang Patelimport android.view.accessibility.AccessibilityEvent;
2988a981b47c7face1b1fdaa9074256245107b9ca9Devang Patelimport android.view.animation.AnimationUtils;
30057afddf0fab91d979d6a750667d56a345225c96Devang Patelimport android.view.animation.Interpolator;
314c4635c6cd8114bfa3ee20628fa1f03e67ac1e55Devang Patelimport android.widget.LinearLayout;
32057afddf0fab91d979d6a750667d56a345225c96Devang Patel
33057afddf0fab91d979d6a750667d56a345225c96Devang Patelimport com.android.systemui.R;
34cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedmanimport com.android.systemui.statusbar.ExpandableView;
35cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedmanimport com.android.systemui.statusbar.GestureRecorder;
360bd41f2cea0639395e8ab7ef8fd6df2c1999b6aeDevang Patelimport com.android.systemui.statusbar.StatusBarState;
3786522b9e84d0c39f09b54e888538ad64e89788c4Devang Patelimport com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
38057afddf0fab91d979d6a750667d56a345225c96Devang Patel
39057afddf0fab91d979d6a750667d56a345225c96Devang Patelpublic class NotificationPanelView extends PanelView implements
4088a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel        ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
4186522b9e84d0c39f09b54e888538ad64e89788c4Devang Patel        View.OnClickListener {
4286522b9e84d0c39f09b54e888538ad64e89788c4Devang Patel    public static final boolean DEBUG_GESTURES = true;
4386522b9e84d0c39f09b54e888538ad64e89788c4Devang Patel    private static final int EXPANSION_ANIMATION_LENGTH = 375;
4486522b9e84d0c39f09b54e888538ad64e89788c4Devang Patel
45cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman    PhoneStatusBar mStatusBar;
46057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private StatusBarHeaderView mHeader;
47057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private QuickSettingsContainerView mQsContainer;
48057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private View mKeyguardStatusView;
49057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private ObservableScrollView mScrollView;
50057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private View mStackScrollerContainer;
51057afddf0fab91d979d6a750667d56a345225c96Devang Patel
52057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private NotificationStackScrollLayout mNotificationStackScroller;
53eae1560d4fb99b9df814bc12c0419825996156cdDevang Patel    private int mNotificationTopPadding;
545bfc1a7ecb853cf87d10e720a07b9fbcd2a223eeDevang Patel    private boolean mAnimateNextTopPaddingChange;
555bfc1a7ecb853cf87d10e720a07b9fbcd2a223eeDevang Patel
565bfc1a7ecb853cf87d10e720a07b9fbcd2a223eeDevang Patel    private Interpolator mExpansionInterpolator;
57057afddf0fab91d979d6a750667d56a345225c96Devang Patel
58f9fef925644a6c40b344a43ab9ebdb08a707de53Devang Patel    private int mTrackingPointer;
59cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman    private VelocityTracker mVelocityTracker;
60057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private boolean mTracking;
61eae1560d4fb99b9df814bc12c0419825996156cdDevang Patel    private boolean mQsExpanded;
62057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private float mInitialHeightOnTouch;
63057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private float mInitialTouchX;
64057afddf0fab91d979d6a750667d56a345225c96Devang Patel    private float mInitialTouchY;
657a4718e813e5e99d478567a482217c7eef8572c5Devang Patel    private float mQsExpansionHeight;
667a4718e813e5e99d478567a482217c7eef8572c5Devang Patel    private int mQsMinExpansionHeight;
676b1da0ea19c12346192f5ea4d70872c13bfcc82aDaniel Dunbar    private int mQsMaxExpansionHeight;
686b1da0ea19c12346192f5ea4d70872c13bfcc82aDaniel Dunbar    private int mMinStackHeight;
69d2d2a11a91d7ddf468bfb70f66362d24806ed601Chris Lattner    private float mNotificationTranslation;
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    private int mStackScrollerIntrinsicPadding;
71b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    private boolean mQsExpansionEnabled = true;
72efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    private ValueAnimator mQsExpansionAnimator;
7388a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel
74b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    public NotificationPanelView(Context context, AttributeSet attrs) {
75b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel        super(context, attrs);
7688a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel    }
77b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel
78b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    public void setStatusBar(PhoneStatusBar bar) {
795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        if (mStatusBar != null) {
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            mStatusBar.setOnFlipRunnable(null);
81fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        }
82fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mStatusBar = bar;
83fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        if (bar != null) {
84fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner            mStatusBar.setOnFlipRunnable(new Runnable() {
85fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner                @Override
86fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner                public void run() {
87fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner                    requestPanelHeightUpdate();
886aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                }
89fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner            });
90fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        }
91fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner    }
92fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner
93fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner    @Override
9457a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman    protected void onFinishInflate() {
95fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        super.onFinishInflate();
96fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mHeader = (StatusBarHeaderView) findViewById(R.id.header);
97fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mHeader.getBackgroundView().setOnClickListener(this);
98fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
99fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mStackScrollerContainer = findViewById(R.id.notification_container_parent);
100fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mQsContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
101fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
10209dc6660487fc2f4a4bb2032e30123d3e0da7230Chris Lattner        mScrollView.setListener(this);
1039619662a1d42e2008b865d3459c0677e149dad1bChris Lattner        mNotificationStackScroller = (NotificationStackScrollLayout)
10430ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel                findViewById(R.id.notification_stack_scroller);
1050ffe89ab1e4890899e0e11a6f68223567a69b38aDevang Patel        mNotificationStackScroller.setOnHeightChangedListener(this);
1069619662a1d42e2008b865d3459c0677e149dad1bChris Lattner        mNotificationTopPadding = getResources().getDimensionPixelSize(
1073c40085b373d8e6e4523812e06f73a0cb9d5142cDevang Patel                R.dimen.notifications_top_padding);
108fae6e2994a51d8ec1e61b6eb68765247c83b1ccfChris Lattner        mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height);
1094581fff8af09a156a9dcc4de62587385c5da9574Chris Lattner        mExpansionInterpolator = AnimationUtils.loadInterpolator(
11047c87b4b160d45285b24b1b7f4e3cbaaed3dc464Devang Patel                getContext(), android.R.interpolator.fast_out_slow_in);
11130ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel    }
11230ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel
1139619662a1d42e2008b865d3459c0677e149dad1bChris Lattner    @Override
1144581fff8af09a156a9dcc4de62587385c5da9574Chris Lattner    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
11530ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel        super.onLayout(changed, left, top, right, bottom);
11630ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel        int keyguardBottomMargin =
11730ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel                ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin;
11857a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman        if (!mQsExpanded) {
11957a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman            mStackScrollerIntrinsicPadding = mStatusBar.getBarState() == StatusBarState.KEYGUARD
12057a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman                    ? mKeyguardStatusView.getBottom() + keyguardBottomMargin
12157a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman                    : mHeader.getBottom() + mNotificationTopPadding;
12257a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman            mNotificationStackScroller.setTopPadding(mStackScrollerIntrinsicPadding,
12357a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman                    mAnimateNextTopPaddingChange);
12457a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman            mAnimateNextTopPaddingChange = false;
1254581fff8af09a156a9dcc4de62587385c5da9574Chris Lattner        }
1264581fff8af09a156a9dcc4de62587385c5da9574Chris Lattner
1274581fff8af09a156a9dcc4de62587385c5da9574Chris Lattner        // Calculate quick setting heights.
1284581fff8af09a156a9dcc4de62587385c5da9574Chris Lattner        mQsMinExpansionHeight = mHeader.getCollapsedHeight();
12919009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner        mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
13019009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner        if (mQsExpansionHeight == 0) {
13119009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner            mQsExpansionHeight = mQsMinExpansionHeight;
13219009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner        }
13319009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner    }
13419009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner
13519009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner    public void animateNextTopPaddingChange() {
13619009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner        mAnimateNextTopPaddingChange = true;
13798be4943e8dc4f3905629a7102668960873cf863Chris Lattner        requestLayout();
13819009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner    }
13919009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner
14019009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner    /**
141b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman     * @return Whether Quick Settings are currently expanded.
142b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman     */
143b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    public boolean isQsExpanded() {
144b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        return mQsExpanded;
145b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    }
146b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
147b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
148b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mQsExpansionEnabled = qsExpansionEnabled;
149b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    }
150b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
151b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    public void closeQs() {
152b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        cancelAnimation();
153b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        setQsExpansion(mQsMinExpansionHeight);
154b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    }
155b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
156c5b8806cda286cf41866176ef98011fdaa68da01Chris Lattner    public void openQs() {
157c5b8806cda286cf41866176ef98011fdaa68da01Chris Lattner        cancelAnimation();
158c5b8806cda286cf41866176ef98011fdaa68da01Chris Lattner        if (mQsExpansionEnabled) {
159efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar            setQsExpansion(mQsMaxExpansionHeight);
160efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar        }
161efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    }
162efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar
1636ef58e36bbbfa232fe8b50309361e841985abfc6Chris Lattner    @Override
1646ef58e36bbbfa232fe8b50309361e841985abfc6Chris Lattner    public void fling(float vel, boolean always) {
1656ef58e36bbbfa232fe8b50309361e841985abfc6Chris Lattner        GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
166d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner        if (gr != null) {
167d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner            gr.tag(
1686ef58e36bbbfa232fe8b50309361e841985abfc6Chris Lattner                "fling " + ((vel > 0) ? "open" : "closed"),
169d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner                "notifications,v=" + vel);
170d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner        }
171d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner        super.fling(vel, always);
172d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner    }
1738fb1dd005f4cb530bca11d622362d39727294420Chris Lattner
1748fb1dd005f4cb530bca11d622362d39727294420Chris Lattner    @Override
175d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1768fb1dd005f4cb530bca11d622362d39727294420Chris Lattner        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
1778fb1dd005f4cb530bca11d622362d39727294420Chris Lattner            event.getText()
178b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman                    .add(getContext().getString(R.string.accessibility_desc_notification_shade));
179b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman            return true;
180b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        }
181b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
182b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        return super.dispatchPopulateAccessibilityEvent(event);
183b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    }
184b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
185b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    @Override
186b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    public boolean onInterceptTouchEvent(MotionEvent event) {
187b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        int pointerIndex = event.findPointerIndex(mTrackingPointer);
188b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        if (pointerIndex < 0) {
189b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman            pointerIndex = 0;
190b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman            mTrackingPointer = event.getPointerId(pointerIndex);
191b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        }
192b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        final float x = event.getX(pointerIndex);
193b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        final float y = event.getY(pointerIndex);
194b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
195b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        switch (event.getActionMasked()) {
196b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman            case MotionEvent.ACTION_DOWN:
197b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman                mInitialTouchY = y;
198d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner                mInitialTouchX = x;
199d86e6bc7ab4388a578daf46e7c76be9122a25072Chris Lattner                initVelocityTracker();
200b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                trackMovement(event);
201b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                if (shouldIntercept(mInitialTouchX, mInitialTouchY, 0)) {
202f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                    getParent().requestDisallowInterceptTouchEvent(true);
203b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                }
204f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                break;
205b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner            case MotionEvent.ACTION_POINTER_UP:
206f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                final int upPointer = event.getPointerId(event.getActionIndex());
207b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                if (mTrackingPointer == upPointer) {
208f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                    // gesture is ongoing, find a new pointer to track
209b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                    final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
210f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                    mTrackingPointer = event.getPointerId(newIndex);
211b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                    mInitialTouchX = event.getX(newIndex);
212f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                    mInitialTouchY = event.getY(newIndex);
213f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                }
214f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                break;
21530ec9972be5a5af1f7a2277360dfa3aa1540b4faDevang Patel
2169619662a1d42e2008b865d3459c0677e149dad1bChris Lattner            case MotionEvent.ACTION_MOVE:
2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                final float h = y - mInitialTouchY;
2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                trackMovement(event);
21972564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)
22072564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                        && shouldIntercept(mInitialTouchX, mInitialTouchY, h)) {
22172564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                    onQsExpansionStarted();
22272564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                    mInitialHeightOnTouch = mQsExpansionHeight;
22372564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                    mInitialTouchY = y;
22472564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                    mInitialTouchX = x;
22572564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                    mTracking = true;
22672564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor                    return true;
2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                }
2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                break;
229afef76e43a30380b3c612a674738f2f574c8f166Argyrios Kyrtzidis        }
2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        return !mQsExpanded && super.onInterceptTouchEvent(event);
2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
233d2d2a11a91d7ddf468bfb70f66362d24806ed601Chris Lattner    @Override
2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    public boolean onTouchEvent(MotionEvent event) {
2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
23619009e6fe7e0f51d2e49f4c94928a048c11c5281Chris Lattner        // implementation.
2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        if (mTracking) {
2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            int pointerIndex = event.findPointerIndex(mTrackingPointer);
239d2d2a11a91d7ddf468bfb70f66362d24806ed601Chris Lattner            if (pointerIndex < 0) {
240d2d2a11a91d7ddf468bfb70f66362d24806ed601Chris Lattner                pointerIndex = 0;
241d2d2a11a91d7ddf468bfb70f66362d24806ed601Chris Lattner                mTrackingPointer = event.getPointerId(pointerIndex);
242d2d2a11a91d7ddf468bfb70f66362d24806ed601Chris Lattner            }
2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            final float y = event.getY(pointerIndex);
2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            final float x = event.getX(pointerIndex);
2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            switch (event.getActionMasked()) {
2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                case MotionEvent.ACTION_DOWN:
2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    mTracking = true;
2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    mInitialTouchY = y;
2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    mInitialTouchX = x;
251afef76e43a30380b3c612a674738f2f574c8f166Argyrios Kyrtzidis                    onQsExpansionStarted();
25247f7dbf7c0b25505ad093a317983a9b39efe0610Chris Lattner                    mInitialHeightOnTouch = mQsExpansionHeight;
25398be4943e8dc4f3905629a7102668960873cf863Chris Lattner                    initVelocityTracker();
2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    trackMovement(event);
255f6a943e047f541619a2202f9e43b20b3d7c0a96dEli Friedman                    break;
256c8b1227fa8c17d9881815e40c04e19334be536f8Nate Begeman
2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                case MotionEvent.ACTION_POINTER_UP:
258b7cfe88e88cb4f46308de89cf3f0c81bfe624128Chris Lattner                    final int upPointer = event.getPointerId(event.getActionIndex());
2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    if (mTrackingPointer == upPointer) {
2605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                        // gesture is ongoing, find a new pointer to track
2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                        final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
262f98aba35e6c3da5aae61843fc01334939e4e12ecEli Friedman                        final float newY = event.getY(newIndex);
263f98aba35e6c3da5aae61843fc01334939e4e12ecEli Friedman                        final float newX = event.getX(newIndex);
2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                        mTrackingPointer = event.getPointerId(newIndex);
265572cf09ae8a78af1c56d40b016ec4cf1837163acChris Lattner                        mInitialHeightOnTouch = mQsExpansionHeight;
266fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner                        mInitialTouchY = newY;
267572cf09ae8a78af1c56d40b016ec4cf1837163acChris Lattner                        mInitialTouchX = newX;
2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    }
2697c80bd64032e610c0dbd74fc0ef6ea334447f2fdSebastian Redl                    break;
2707c80bd64032e610c0dbd74fc0ef6ea334447f2fdSebastian Redl
2716aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                case MotionEvent.ACTION_MOVE:
2726aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                    final float h = y - mInitialTouchY;
2736aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                    setQsExpansion(h + mInitialHeightOnTouch);
2746aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                    trackMovement(event);
2756aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                    break;
2766aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar
2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                case MotionEvent.ACTION_UP:
2786aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                case MotionEvent.ACTION_CANCEL:
279fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner                    mTracking = false;
280fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner                    mTrackingPointer = -1;
2816aeae7fa9cfaacba3a4077d62c01c2531d88a63eDaniel Dunbar                    trackMovement(event);
282fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner
2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    float vel = getCurrentVelocity();
2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
285fb22d96692c5240fb8d611290dbf7eeed3759c73Steve Naroff                    // TODO: Better logic whether we should expand or not.
286fb22d96692c5240fb8d611290dbf7eeed3759c73Steve Naroff                    flingSettings(vel, vel > 0);
287c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman
2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                    if (mVelocityTracker != null) {
289c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman                        mVelocityTracker.recycle();
290c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman                        mVelocityTracker = null;
29157a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman                    }
292c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman                    break;
293c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman            }
294c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman            return true;
295c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman        }
296c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman
297c5773c4b8ce1ed6ed5c7112c9020c954a47dce96Eli Friedman        // Consume touch events when QS are expanded.
29857a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman        return mQsExpanded || super.onTouchEvent(event);
2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
300fb22d96692c5240fb8d611290dbf7eeed3759c73Steve Naroff
301fb22d96692c5240fb8d611290dbf7eeed3759c73Steve Naroff    private void onQsExpansionStarted() {
30257a84fb51de4f3de50debcf12dd194af8c6aaa58Eli Friedman        cancelAnimation();
303fb22d96692c5240fb8d611290dbf7eeed3759c73Steve Naroff
304fb22d96692c5240fb8d611290dbf7eeed3759c73Steve Naroff        // Reset scroll position and apply that position to the expanded height.
305213541a68a3e137d11d2cefb612c6cdb410d7e8eNate Begeman        float height = mQsExpansionHeight - mScrollView.getScrollY();
3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        mScrollView.scrollTo(0, 0);
3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        setQsExpansion(height);
308fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner    }
3095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    private void expandQs() {
3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        mHeader.setExpanded(true);
312bb36d331f439f49859efcfb4435c61762fbba6f9Daniel Dunbar        mNotificationStackScroller.setEnabled(false);
313b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mScrollView.setVisibility(View.VISIBLE);
314b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mQsExpanded = true;
315b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    }
316b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
317b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    private void collapseQs() {
318b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mHeader.setExpanded(false);
319b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mNotificationStackScroller.setEnabled(true);
320b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mScrollView.setVisibility(View.INVISIBLE);
321b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        mQsExpanded = false;
322b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    }
323b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman
324b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman    private void setQsExpansion(float height) {
3259a1a9c41cf7e2735f059bb0c1d85f3207f637b22Chris Lattner        height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
326b3b6b9b27ab8bdb2a435a5a92ce62e74e3399377Eli Friedman        if (height > mQsMinExpansionHeight && !mQsExpanded) {
3279a1a9c41cf7e2735f059bb0c1d85f3207f637b22Chris Lattner            expandQs();
3289a1a9c41cf7e2735f059bb0c1d85f3207f637b22Chris Lattner        } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
3299a1a9c41cf7e2735f059bb0c1d85f3207f637b22Chris Lattner            collapseQs();
330bb36d331f439f49859efcfb4435c61762fbba6f9Daniel Dunbar        }
331ebb97e98c03f8d7034bd3748a10e35f39a95c289Christopher Lamb        mQsExpansionHeight = height;
332f11284ac87daa613bc7b30db9f54bd716d123222Fariborz Jahanian        mHeader.setExpansion(height);
333fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        setQsTranslation(height);
334f11284ac87daa613bc7b30db9f54bd716d123222Fariborz Jahanian        setQsStackScrollerPadding(height);
335b1776cb8d35dfa80bfd8606e58b8ade30dcd2438Chris Lattner    }
336636efb6ee4382e6fc16724014e9cf70dbeb37c31Chris Lattner
337636efb6ee4382e6fc16724014e9cf70dbeb37c31Chris Lattner    private void setQsTranslation(float height) {
338636efb6ee4382e6fc16724014e9cf70dbeb37c31Chris Lattner        mQsContainer.setY(height - mQsContainer.getHeight());
339636efb6ee4382e6fc16724014e9cf70dbeb37c31Chris Lattner    }
340636efb6ee4382e6fc16724014e9cf70dbeb37c31Chris Lattner
341636efb6ee4382e6fc16724014e9cf70dbeb37c31Chris Lattner    private void setQsStackScrollerPadding(float height) {
342391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner        float start = height - mScrollView.getScrollY() + mNotificationTopPadding;
343412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar        float stackHeight = mNotificationStackScroller.getHeight() - start;
344412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar        if (stackHeight <= mMinStackHeight) {
345412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar            float overflow = mMinStackHeight - stackHeight;
346412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar            stackHeight = mMinStackHeight;
347412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar            start = mNotificationStackScroller.getHeight() - stackHeight;
348412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar            mNotificationStackScroller.setTranslationY(overflow);
349412f59b23fc502b199b9ca96c72ef5d5ad21d62bDaniel Dunbar            mNotificationTranslation = overflow + mScrollView.getScrollY();
350391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner        } else {
351e37882ad335896dedf345102bb425383e6221c37Fariborz Jahanian            mNotificationStackScroller.setTranslationY(0);
352a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek            mNotificationTranslation = mScrollView.getScrollY();
35398c5ead87d720d8b68b6f236c3c3579a388fc882Daniel Dunbar        }
35498c5ead87d720d8b68b6f236c3c3579a388fc882Daniel Dunbar        mNotificationStackScroller.setTopPadding(clampQsStackScrollerPadding((int) start), false);
355c569249ca0ab755ac79d8cbbfcb2bcae19743624Fariborz Jahanian    }
35672564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor
35772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor    private int clampQsStackScrollerPadding(int desiredPadding) {
358de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner        return Math.max(desiredPadding, mStackScrollerIntrinsicPadding);
3598fb1dd005f4cb530bca11d622362d39727294420Chris Lattner    }
360de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner
361de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner    private void trackMovement(MotionEvent event) {
362de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner        if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
363de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner    }
364de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner
365de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner    private void initVelocityTracker() {
366de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner        if (mVelocityTracker != null) {
367d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner            mVelocityTracker.recycle();
368de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner        }
369d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner        mVelocityTracker = VelocityTracker.obtain();
370de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner    }
371de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner
372de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner    private float getCurrentVelocity() {
373de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner        if (mVelocityTracker == null) {
374de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner            return 0;
375de0efb3b6eac36bdeae0e60f753a974cc4118a31Chris Lattner        }
3769048891ff983d0681c116c6e8f1073aa31bdd6e8Daniel Dunbar        mVelocityTracker.computeCurrentVelocity(1000);
3779048891ff983d0681c116c6e8f1073aa31bdd6e8Daniel Dunbar        return mVelocityTracker.getYVelocity();
3784e174f1b1e95faacc21da2eac70f7853807f3ea3Daniel Dunbar    }
379209bb438042ef7652b2b046e43d4ffb5a00d9725Fariborz Jahanian
380209bb438042ef7652b2b046e43d4ffb5a00d9725Fariborz Jahanian    private void cancelAnimation() {
381209bb438042ef7652b2b046e43d4ffb5a00d9725Fariborz Jahanian        if (mQsExpansionAnimator != null) {
3829048891ff983d0681c116c6e8f1073aa31bdd6e8Daniel Dunbar            mQsExpansionAnimator.cancel();
383424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl        }
384424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl    }
385424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl    private void flingSettings(float vel, boolean expand) {
386424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl
387424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl        // TODO: Actually use velocity.
388424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl
389424c51d3d4bea87291919b75e73ca59386702ad5Sebastian Redl        float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
3907532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
3917532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        animator.setDuration(EXPANSION_ANIMATION_LENGTH);
3927532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        animator.setInterpolator(mExpansionInterpolator);
3935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
3945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            @Override
3955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            public void onAnimationUpdate(ValueAnimator animation) {
3965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                setQsExpansion((Float) animation.getAnimatedValue());
3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            }
3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        });
399fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        animator.addListener(new AnimatorListenerAdapter() {
400fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner            @Override
4018fb1dd005f4cb530bca11d622362d39727294420Chris Lattner            public void onAnimationEnd(Animator animation) {
402efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar                mQsExpansionAnimator = null;
403efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar            }
404efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar        });
405efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar        animator.start();
406efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar        mQsExpansionAnimator = animator;
407efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    }
408fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner
4095de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    /**
4105de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner     * @return Whether we should intercept a gesture to open Quick Settings.
411fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner     */
412fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner    private boolean shouldIntercept(float x, float y, float yDiff) {
4135de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        if (!mQsExpansionEnabled) {
4145de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner            return false;
415fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        }
4165de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        View headerView = mStatusBar.getBarState() == StatusBarState.KEYGUARD && !mQsExpanded
417efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar                ? mKeyguardStatusView
4185de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner                : mHeader;
4195de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        boolean onHeader = x >= headerView.getLeft() && x <= headerView.getRight()
4205de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner                && y >= headerView.getTop() && y <= headerView.getBottom();
4215de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        if (mQsExpanded) {
4225de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner            return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0);
42339ba4aeca296b1c9f04bde7d9d3cbbf129f1abd3Argyrios Kyrtzidis        } else {
424fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner            return onHeader;
425fce71b8ea53b6eb9c1630da24659289bc848f837Chris Lattner        }
4265de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    }
4275de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner
4285de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    @Override
4295de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    public void setVisibility(int visibility) {
4305de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        int oldVisibility = getVisibility();
4315de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        super.setVisibility(visibility);
4325de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        if (visibility != oldVisibility) {
4335de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner            reparentStatusIcons(visibility == VISIBLE);
4345de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        }
435efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    }
4365de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner
4375de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    /**
4385de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner     * When the notification panel gets expanded, we need to move the status icons in the header
439ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar     * card.
440ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar     */
441ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar    private void reparentStatusIcons(boolean toHeader) {
442ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar        if (mStatusBar == null) {
443ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar            return;
444fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        }
445cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman        LinearLayout systemIcons = mStatusBar.getSystemIcons();
446fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        if (systemIcons.getParent() != null) {
447ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar            ((ViewGroup) systemIcons.getParent()).removeView(systemIcons);
448ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar        }
449ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar        if (toHeader) {
450ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar            mHeader.attachSystemIcons(systemIcons);
451ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar        } else {
452ae287239879386b9abf6da50a67bbb7fe81897f1Daniel Dunbar            mStatusBar.reattachSystemIcons();
453fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        }
4545de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    }
455efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar
456efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    @Override
457efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    protected boolean isScrolledToBottom() {
458efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar        if (!isInSettings()) {
4595de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner            return mNotificationStackScroller.isScrolledToBottom();
460fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        }
461fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner        return super.isScrolledToBottom();
4625de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    }
4635de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner
4645de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    @Override
4655de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner    protected int getMaxPanelHeight() {
4665de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner        if (!isInSettings()) {
4675de00fcf7c923a14bb79bdbaabb2faeb5633d85aChris Lattner            int maxPanelHeight = super.getMaxPanelHeight();
468fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner            int notificationMarginBottom = mStackScrollerContainer.getPaddingBottom();
469fc3b8e9c1381d5e6ec361591d649c56a870ff971Chris Lattner            int emptyBottomMargin = notificationMarginBottom
470b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel                    + mNotificationStackScroller.getEmptyBottomMargin();
471b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel            return maxPanelHeight - emptyBottomMargin;
472b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel        }
473ce5605ecf76d8cde6372138f830bb144d174ced9Chris Lattner        return super.getMaxPanelHeight();
47421fdf416723e8c475812a0324a1f9fafc949c25fHartmut Kaiser    }
475391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner
476391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner    private boolean isInSettings() {
477391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner        return mQsExpanded;
478c4c429a1a5947ba9be64d3070741d98362872265Devang Patel    }
4792c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio
4802c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    @Override
4812c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    protected void onHeightUpdated(float expandedHeight) {
4822c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio        mNotificationStackScroller.setStackHeight(expandedHeight);
4832c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    }
4842c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio
4852c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    @Override
4862c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    protected int getDesiredMeasureHeight() {
4872c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio        return mMaxPanelHeight;
4882c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    }
4892c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio
4902c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    @Override
4912c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    protected void onExpandingStarted() {
4922c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio        super.onExpandingStarted();
4931abc7f654df795549d4f6f3a018ddb3a8fff013aNate Begeman        mNotificationStackScroller.onExpansionStarted();
4942c46ce8de96787aa8e040690a80896f1148c29b0Lauro Ramos Venancio    }
495b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel
496b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    @Override
49788a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel    protected void onExpandingFinished() {
49888a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel        super.onExpandingFinished();
499af31913e48c96fddb45a0fd33f25617546502cbbChris Lattner        mNotificationStackScroller.onExpansionStopped();
500efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    }
501efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar
502efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    @Override
503efb6d0dc3eafbcf4f8cd053138bd1abed1dda8d4Daniel Dunbar    public void onHeightChanged(ExpandableView view) {
50488a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel        requestPanelHeightUpdate();
505b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    }
506b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel
507b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    @Override
508b84a06e68ffd71da22e3c75b6e4bbdba37816413Devang Patel    public void onScrollChanged() {
50986522b9e84d0c39f09b54e888538ad64e89788c4Devang Patel        if (mQsExpanded) {
510cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman            mNotificationStackScroller.setTranslationY(
511cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman                    mNotificationTranslation - mScrollView.getScrollY());
512cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman        }
513cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman    }
51488a981b47c7face1b1fdaa9074256245107b9ca9Devang Patel
515e36a3c8b5c7db4916342e4381caa2fdc93eb5745Eli Friedman    @Override
516e36a3c8b5c7db4916342e4381caa2fdc93eb5745Eli Friedman    public void onClick(View v) {
517e36a3c8b5c7db4916342e4381caa2fdc93eb5745Eli Friedman        if (v == mHeader.getBackgroundView()) {
518e36a3c8b5c7db4916342e4381caa2fdc93eb5745Eli Friedman            onQsExpansionStarted();
519cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman            if (mQsExpanded) {
520e36a3c8b5c7db4916342e4381caa2fdc93eb5745Eli Friedman                flingSettings(0 /* vel */, false /* expand */);
521cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman            } else if (mQsExpansionEnabled) {
522cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman                flingSettings(0 /* vel */, true /* expand */);
52344b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor            }
5246ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor        }
5256ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor    }
52644b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor}
527cbadaf6ced6d664015ee409f62ab1bc20ae0bf73Eli Friedman