DragDownHelper.java revision 567e845d99840a6e556595739a15e16132eb2f1e
1ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi/*
2ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * Copyright (C) 2014 The Android Open Source Project
3ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *
4ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
5ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * you may not use this file except in compliance with the License.
6ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * You may obtain a copy of the License at
7ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *
8ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
9ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *
10ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * Unless required by applicable law or agreed to in writing, software
11ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
12ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * See the License for the specific language governing permissions and
14ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * limitations under the License
15ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi */
16ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
17ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggipackage com.android.systemui.statusbar;
18ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
194222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggiimport android.animation.Animator;
204222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggiimport android.animation.AnimatorListenerAdapter;
214222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggiimport android.animation.ObjectAnimator;
2248bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggiimport android.animation.ValueAnimator;
23ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.content.Context;
24ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.view.MotionEvent;
25ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.view.View;
26ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.view.ViewConfiguration;
27c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek
28ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport com.android.systemui.ExpandHelper;
29ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport com.android.systemui.Gefingerpoken;
30c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport com.android.systemui.Interpolators;
31ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport com.android.systemui.R;
320e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport com.android.systemui.classifier.FalsingManager;
33ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
34ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi/**
35ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
36ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * the notification where the drag started.
37ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi */
38ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggipublic class DragDownHelper implements Gefingerpoken {
39ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
404222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private static final float RUBBERBAND_FACTOR_EXPANDABLE = 0.5f;
414222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private static final float RUBBERBAND_FACTOR_STATIC = 0.15f;
424222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
434222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private static final int SPRING_BACK_ANIMATION_LENGTH_MS = 375;
444222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
45ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private int mMinDragDistance;
46ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private ExpandHelper.Callback mCallback;
47ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private float mInitialTouchX;
48ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private float mInitialTouchY;
49ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private boolean mDraggingDown;
50ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private float mTouchSlop;
5148bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi    private DragDownCallback mDragDownCallback;
52ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private View mHost;
53ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private final int[] mTemp2 = new int[2];
54ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private boolean mDraggedFarEnough;
554222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private ExpandableView mStartingChild;
5648bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi    private float mLastHeight;
570e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    private FalsingManager mFalsingManager;
58ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
59ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
6048bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi            DragDownCallback dragDownCallback) {
61ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mMinDragDistance = context.getResources().getDimensionPixelSize(
62ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                R.dimen.keyguard_drag_down_min_distance);
63ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
64ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mCallback = callback;
6548bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        mDragDownCallback = dragDownCallback;
66ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mHost = host;
670e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        mFalsingManager = FalsingManager.getInstance(context);
68ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
69ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
70ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    @Override
71ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public boolean onInterceptTouchEvent(MotionEvent event) {
72ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float x = event.getX();
73ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float y = event.getY();
74ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
75ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        switch (event.getActionMasked()) {
76ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_DOWN:
77ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mDraggedFarEnough = false;
78ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mDraggingDown = false;
79ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mStartingChild = null;
80ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mInitialTouchY = y;
81ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mInitialTouchX = x;
82ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                break;
83ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
84ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_MOVE:
85ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                final float h = y - mInitialTouchY;
86ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
870e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski                    mFalsingManager.onNotificatonStartDraggingDown();
88ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mDraggingDown = true;
894222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                    captureStartingChild(mInitialTouchX, mInitialTouchY);
90ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mInitialTouchY = y;
91ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mInitialTouchX = x;
9248bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                    mDragDownCallback.onTouchSlopExceeded();
93ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    return true;
94ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
95ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                break;
96ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
97ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        return false;
98ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
99ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
100ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    @Override
101ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public boolean onTouchEvent(MotionEvent event) {
102ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        if (!mDraggingDown) {
103ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            return false;
104ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
105ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float x = event.getX();
106ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float y = event.getY();
107ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
108ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        switch (event.getActionMasked()) {
109ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_MOVE:
11048bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                mLastHeight = y - mInitialTouchY;
1114222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                captureStartingChild(mInitialTouchX, mInitialTouchY);
1124222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                if (mStartingChild != null) {
11348bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                    handleExpansion(mLastHeight, mStartingChild);
11448bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                } else {
11548bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                    mDragDownCallback.setEmptyDragAmount(mLastHeight);
116ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
11748bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                if (mLastHeight > mMinDragDistance) {
118ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    if (!mDraggedFarEnough) {
119ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                        mDraggedFarEnough = true;
120177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek                        mDragDownCallback.onCrossedThreshold(true);
121ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    }
122ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                } else {
123ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    if (mDraggedFarEnough) {
124ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                        mDraggedFarEnough = false;
125177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek                        mDragDownCallback.onCrossedThreshold(false);
126ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    }
127ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
128ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                return true;
129ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_UP:
1306dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski                if (!isFalseTouch() && mDragDownCallback.onDraggedDown(mStartingChild,
131b018399a3a2762e95126acbe14397eca15bad772Christoph Studer                        (int) (y - mInitialTouchY))) {
132dbc3dce886cb7abba23a9f18e60d0f5af5c93226Jorim Jaggi                    if (mStartingChild == null) {
13348bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                        mDragDownCallback.setEmptyDragAmount(0f);
1345243c12f49fbe0ab8fe6b3b2be368783cd2b2a7bSelim Cinek                    } else {
1355243c12f49fbe0ab8fe6b3b2be368783cd2b2a7bSelim Cinek                        mCallback.setUserLockedChild(mStartingChild, false);
1364222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                    }
13798fb09c2b2dbf57803a8737ee7b73cf167721312Jorim Jaggi                    mDraggingDown = false;
138ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                } else {
139ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    stopDragging();
140ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    return false;
141ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
142ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                break;
143ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_CANCEL:
144ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                stopDragging();
145ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                return false;
146ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
147ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        return false;
148ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
149ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
1506dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski    private boolean isFalseTouch() {
15152af6b646bd3abc8223ed01a36f6da785b35085dBlazej Magnowski        return mFalsingManager.isFalseTouch() || !mDraggedFarEnough;
1526dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski    }
1536dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski
1544222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private void captureStartingChild(float x, float y) {
1554222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        if (mStartingChild == null) {
1564222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            mStartingChild = findView(x, y);
1574222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            if (mStartingChild != null) {
1584222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                mCallback.setUserLockedChild(mStartingChild, true);
1594222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            }
1604222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        }
161ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
162ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
1634222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private void handleExpansion(float heightDelta, ExpandableView child) {
1644222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        if (heightDelta < 0) {
1654222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            heightDelta = 0;
166ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
1674222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        boolean expandable = child.isContentExpandable();
1684222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        float rubberbandFactor = expandable
1694222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                ? RUBBERBAND_FACTOR_EXPANDABLE
1704222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                : RUBBERBAND_FACTOR_STATIC;
1714222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        float rubberband = heightDelta * rubberbandFactor;
1722c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek        if (expandable
173567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek                && (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
1742c58461daf909fae5a2605f0ba63da3f9c897731Selim Cinek            float overshoot =
175567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek                    (rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
1764222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
1774222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            rubberband -= overshoot;
178ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
179567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek        child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
1804222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
1814222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
1824222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private void cancelExpansion(final ExpandableView child) {
183567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek        if (child.getActualHeight() == child.getCollapsedHeight()) {
1845243c12f49fbe0ab8fe6b3b2be368783cd2b2a7bSelim Cinek            mCallback.setUserLockedChild(child, false);
1854222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            return;
1864222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        }
187eef842851026a90b6a217d8bc423454fa48df4feSelim Cinek        ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
188567e845d99840a6e556595739a15e16132eb2f1eSelim Cinek                child.getActualHeight(), child.getCollapsedHeight());
189c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek        anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
1904222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
1914222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        anim.addListener(new AnimatorListenerAdapter() {
1924222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            @Override
1934222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            public void onAnimationEnd(Animator animation) {
1944222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi                mCallback.setUserLockedChild(child, false);
1954222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            }
1964222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        });
1974222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        anim.start();
1984222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
1994222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
20048bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi    private void cancelExpansion() {
20148bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        ValueAnimator anim = ValueAnimator.ofFloat(mLastHeight, 0);
202c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek        anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
20348bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
20448bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
20548bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi            @Override
20648bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi            public void onAnimationUpdate(ValueAnimator animation) {
20748bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi                mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
20848bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi            }
20948bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        });
21048bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        anim.start();
21148bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi    }
21248bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi
2134222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private void stopDragging() {
2140e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        mFalsingManager.onNotificatonStopDraggingDown();
2154222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        if (mStartingChild != null) {
2164222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi            cancelExpansion(mStartingChild);
21748bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        } else {
21848bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi            cancelExpansion();
2194222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        }
2204222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        mDraggingDown = false;
22148bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        mDragDownCallback.onDragDownReset();
222ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
223ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
2244222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    private ExpandableView findView(float x, float y) {
225ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mHost.getLocationOnScreen(mTemp2);
226ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        x += mTemp2[0];
227ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        y += mTemp2[1];
228ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        return mCallback.getChildAtRawPosition(x, y);
229ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
230ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
23148bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi    public interface DragDownCallback {
23248bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi
23348bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        /**
23448bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi         * @return true if the interaction is accepted, false if it should be cancelled
23548bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi         */
236b018399a3a2762e95126acbe14397eca15bad772Christoph Studer        boolean onDraggedDown(View startingChild, int dragLengthY);
237d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        void onDragDownReset();
238177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek
239177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek        /**
240177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek         * The user has dragged either above or below the threshold
241177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek         * @param above whether he dragged above it
242177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek         */
243177fd4324ab89dc138b3d4c7472623ae9dc8c9d8Selim Cinek        void onCrossedThreshold(boolean above);
2441408eb5a58d669933c701e347fd3498ceab70f3cSelim Cinek        void onTouchSlopExceeded();
24548bc36af053885daf091bcca6d99411e0438ba83Jorim Jaggi        void setEmptyDragAmount(float amount);
246ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
247ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi}
248