107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka/*
207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * Copyright (C) 2011 The Android Open Source Project
307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka *
407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * you may not use this file except in compliance with the License.
607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * You may obtain a copy of the License at
707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka *
807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka *
1007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * Unless required by applicable law or agreed to in writing, software
1107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
1207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * See the License for the specific language governing permissions and
1407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka * limitations under the License.
1507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka */
1607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkapackage com.android.systemui;
1807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.animation.Animator;
202f2022afa1eb85018368398bd150e9575fc099c9Chet Haaseimport android.animation.AnimatorListenerAdapter;
2107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.animation.ObjectAnimator;
2207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.animation.ValueAnimator;
2307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.animation.ValueAnimator.AnimatorUpdateListener;
24eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandlerimport android.content.Context;
2507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.graphics.RectF;
26f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandlerimport android.os.Handler;
2707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.util.Log;
2807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.view.MotionEvent;
2907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.view.VelocityTracker;
3007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport android.view.View;
31f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandlerimport android.view.ViewConfiguration;
32de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport android.view.accessibility.AccessibilityEvent;
3307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
346dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowskiimport com.android.systemui.classifier.FalsingManager;
3595d743c38c919dd500d9dcacf9f998500d403d9eMady Mellorimport com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
3695d743c38c919dd500d9dcacf9f998500d403d9eMady Mellorimport com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
3795d743c38c919dd500d9dcacf9f998500d403d9eMady Mellorimport com.android.systemui.statusbar.ExpandableNotificationRow;
38287963146c96a4cd2772cfee829ac4a4a03c1ff7Mady Mellorimport com.android.systemui.statusbar.FlingAnimationUtils;
396dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski
4030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwanimport java.util.HashMap;
4130637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
426a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerpublic class SwipeHelper implements Gefingerpoken {
4307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    static final String TAG = "com.android.systemui.SwipeHelper";
4496f4818ef41141649337d4dee09f837594e93d09Daniel Sandler    private static final boolean DEBUG = false;
4507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private static final boolean DEBUG_INVALIDATE = false;
4607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
473cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka    private static final boolean CONSTRAIN_SWIPE = true;
483cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka    private static final boolean FADE_OUT_DURING_SWIPE = true;
493cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka    private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true;
5007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
5107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    public static final int X = 0;
5207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    public static final int Y = 1;
5307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
545574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor    private float SWIPE_ESCAPE_VELOCITY = 500f; // dp/sec
550e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka    private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
560e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka    private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
57bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    private int MAX_DISMISS_VELOCITY = 4000; // dp/sec
580e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka    private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 150; // ms
5907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
605d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos    static final float SWIPE_PROGRESS_FADE_END = 0.5f; // fraction of thumbnail width
615d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos                                              // beyond which swipe progress->0
625574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor    public static final float SWIPED_FAR_ENOUGH_SIZE_FRACTION = 0.6f;
635574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor    static final float MAX_SCROLL_SIZE_FRACTION = 0.3f;
645574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor
655d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos    private float mMinSwipeProgress = 0f;
665d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos    private float mMaxSwipeProgress = 1f;
6707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
68287963146c96a4cd2772cfee829ac4a4a03c1ff7Mady Mellor    private FlingAnimationUtils mFlingAnimationUtils;
6907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private float mPagingTouchSlop;
7007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private Callback mCallback;
71f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler    private Handler mHandler;
7207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private int mSwipeDirection;
7307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private VelocityTracker mVelocityTracker;
746dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski    private FalsingManager mFalsingManager;
7507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
7607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private float mInitialTouchPos;
779b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi    private float mPerpendicularInitialTouchPos;
7807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private boolean mDragging;
7930637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan    private boolean mSnappingChild;
8007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private View mCurrView;
813cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka    private boolean mCanCurrViewBeDimissed;
8207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private float mDensityScale;
834b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    private float mTranslation = 0;
8407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
85f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler    private boolean mLongPressSent;
864247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    private LongPressListener mLongPressListener;
87f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler    private Runnable mWatchLongPress;
88469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler    private long mLongPressTimeout;
89f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler
904247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    final private int[] mTmpPos = new int[2];
9119c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek    private int mFalsingThreshold;
9219c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek    private boolean mTouchAboveFalsingThreshold;
93671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson    private boolean mDisableHwLayers;
9443c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor    private Context mContext;
954247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler
9630637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan    private HashMap<View, Animator> mDismissPendingMap = new HashMap<>();
9730637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
98eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler    public SwipeHelper(int swipeDirection, Callback callback, Context context) {
9943c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor        mContext = context;
10007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        mCallback = callback;
101f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler        mHandler = new Handler();
10207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        mSwipeDirection = swipeDirection;
10307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        mVelocityTracker = VelocityTracker.obtain();
104eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        mDensityScale =  context.getResources().getDisplayMetrics().density;
105eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        mPagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
106469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler
107469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler        mLongPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f); // extra long-press!
10819c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek        mFalsingThreshold = context.getResources().getDimensionPixelSize(
10919c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek                R.dimen.swipe_helper_falsing_threshold);
1106dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski        mFalsingManager = FalsingManager.getInstance(context);
111bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
11207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
11307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1144247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    public void setLongPressListener(LongPressListener listener) {
115f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler        mLongPressListener = listener;
116f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler    }
117f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler
11807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    public void setDensityScale(float densityScale) {
11907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        mDensityScale = densityScale;
12007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
12107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
12207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    public void setPagingTouchSlop(float pagingTouchSlop) {
12307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        mPagingTouchSlop = pagingTouchSlop;
12407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
12507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
126671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson    public void setDisableHardwareLayers(boolean disableHwLayers) {
127671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson        mDisableHwLayers = disableHwLayers;
128671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson    }
129671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson
13007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private float getPos(MotionEvent ev) {
13107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        return mSwipeDirection == X ? ev.getX() : ev.getY();
13207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
13307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1349b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi    private float getPerpendicularPos(MotionEvent ev) {
1359b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi        return mSwipeDirection == X ? ev.getY() : ev.getX();
1369b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi    }
1379b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi
1384b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    protected float getTranslation(View v) {
1393cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka        return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY();
14007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
14107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
14207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private float getVelocity(VelocityTracker vt) {
14307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        return mSwipeDirection == X ? vt.getXVelocity() :
14407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                vt.getYVelocity();
14507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
14607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1474b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    protected ObjectAnimator createTranslationAnimation(View v, float newPos) {
14807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        ObjectAnimator anim = ObjectAnimator.ofFloat(v,
149c5fd350522d9269e6239af818f7261a6ead51570Winson                mSwipeDirection == X ? View.TRANSLATION_X : View.TRANSLATION_Y, newPos);
15007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        return anim;
15107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
15207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
15307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    private float getPerpendicularVelocity(VelocityTracker vt) {
15407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        return mSwipeDirection == X ? vt.getYVelocity() :
15507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                vt.getXVelocity();
15607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
15707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1584b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    protected Animator getViewTranslationAnimator(View v, float target,
1594b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor            AnimatorUpdateListener listener) {
1604b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        ObjectAnimator anim = createTranslationAnimation(v, target);
16134958fa272c9216db4002546c3efad692b3d7775Mady Mellor        if (listener != null) {
16234958fa272c9216db4002546c3efad692b3d7775Mady Mellor            anim.addUpdateListener(listener);
16334958fa272c9216db4002546c3efad692b3d7775Mady Mellor        }
1644b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        return anim;
1654b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    }
1664b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
1674b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    protected void setTranslation(View v, float translate) {
1684b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        if (v == null) {
1694b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor            return;
1704b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        }
17107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        if (mSwipeDirection == X) {
17207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            v.setTranslationX(translate);
17307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        } else {
17407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            v.setTranslationY(translate);
17507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
17607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
17707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
178671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson    protected float getSize(View v) {
17907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        return mSwipeDirection == X ? v.getMeasuredWidth() :
18007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                v.getMeasuredHeight();
18107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
18207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
1835d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos    public void setMinSwipeProgress(float minSwipeProgress) {
1845d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos        mMinSwipeProgress = minSwipeProgress;
1854eaa983f253d0215d4de777edd8616318610ea22Michael Jurka    }
1864eaa983f253d0215d4de777edd8616318610ea22Michael Jurka
1875d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos    public void setMaxSwipeProgress(float maxSwipeProgress) {
1885d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos        mMaxSwipeProgress = maxSwipeProgress;
189de61fd7822ea15fb691405c1aae472caa58e83baAdrian Roos    }
190de61fd7822ea15fb691405c1aae472caa58e83baAdrian Roos
191bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    private float getSwipeProgressForOffset(View view, float translation) {
1923cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka        float viewSize = getSize(view);
193bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        float result = Math.abs(translation / viewSize);
1945d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos        return Math.min(Math.max(mMinSwipeProgress, result), mMaxSwipeProgress);
19507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
19607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
197bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    private float getSwipeAlpha(float progress) {
198bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        return Math.min(0, Math.max(1, progress / SWIPE_PROGRESS_FADE_END));
199bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    }
200bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson
2015d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos    private void updateSwipeProgressFromOffset(View animView, boolean dismissable) {
202bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        updateSwipeProgressFromOffset(animView, dismissable, getTranslation(animView));
203bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    }
204bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson
205bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    private void updateSwipeProgressFromOffset(View animView, boolean dismissable,
206bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson            float translation) {
207bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        float swipeProgress = getSwipeProgressForOffset(animView, translation);
2085d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos        if (!mCallback.updateSwipeProgress(animView, dismissable, swipeProgress)) {
2095d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos            if (FADE_OUT_DURING_SWIPE && dismissable) {
2105d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos                float alpha = swipeProgress;
211671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                if (!mDisableHwLayers) {
212671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                    if (alpha != 0f && alpha != 1f) {
213671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                        animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
214671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                    } else {
215671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                        animView.setLayerType(View.LAYER_TYPE_NONE, null);
216671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                    }
2175d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos                }
218bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson                animView.setAlpha(getSwipeAlpha(swipeProgress));
219499293f096ef3182ef39e42cc06284501022b5cfMichael Jurka            }
22067b03701b633c293fd960435cd97fc0835e44568Michael Jurka        }
22167b03701b633c293fd960435cd97fc0835e44568Michael Jurka        invalidateGlobalRegion(animView);
22267b03701b633c293fd960435cd97fc0835e44568Michael Jurka    }
22367b03701b633c293fd960435cd97fc0835e44568Michael Jurka
224a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    // invalidate the view's own bounds all the way up the view hierarchy
225a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public static void invalidateGlobalRegion(View view) {
226a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        invalidateGlobalRegion(
227a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            view,
228a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
229a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
230a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
231a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    // invalidate a rectangle relative to the view's coordinate system all the way up the view
232a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    // hierarchy
233a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public static void invalidateGlobalRegion(View view, RectF childBounds) {
23496f4818ef41141649337d4dee09f837594e93d09Daniel Sandler        //childBounds.offset(view.getTranslationX(), view.getTranslationY());
23507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        if (DEBUG_INVALIDATE)
23607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            Log.v(TAG, "-------------");
23707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        while (view.getParent() != null && view.getParent() instanceof View) {
23807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            view = (View) view.getParent();
23907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            view.getMatrix().mapRect(childBounds);
24007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            view.invalidate((int) Math.floor(childBounds.left),
24107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                            (int) Math.floor(childBounds.top),
24207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                            (int) Math.ceil(childBounds.right),
24307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                            (int) Math.ceil(childBounds.bottom));
24407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            if (DEBUG_INVALIDATE) {
24507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
24607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        + "," + (int) Math.floor(childBounds.top)
24707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        + "," + (int) Math.ceil(childBounds.right)
24807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        + "," + (int) Math.ceil(childBounds.bottom));
24907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            }
25007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
25107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
25207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
253469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler    public void removeLongPressCallback() {
254f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler        if (mWatchLongPress != null) {
255f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler            mHandler.removeCallbacks(mWatchLongPress);
256491d3a9bfab844bf8587545bb1cdab76d2cd4b96Daniel Sandler            mWatchLongPress = null;
257f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler        }
258f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler    }
259f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler
26043c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor    @Override
2614247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    public boolean onInterceptTouchEvent(final MotionEvent ev) {
26207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        final int action = ev.getAction();
26307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
26407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        switch (action) {
26507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_DOWN:
26619c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek                mTouchAboveFalsingThreshold = false;
26707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                mDragging = false;
26830637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                mSnappingChild = false;
269f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                mLongPressSent = false;
27007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                mVelocityTracker.clear();
2714b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                mCurrView = mCallback.getChildAtPosition(ev);
2724b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
27321ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka                if (mCurrView != null) {
27495d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                    onDownUpdate(mCurrView, ev);
27521ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka                    mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
27621ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka                    mVelocityTracker.addMovement(ev);
27721ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka                    mInitialTouchPos = getPos(ev);
2789b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi                    mPerpendicularInitialTouchPos = getPerpendicularPos(ev);
2794b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                    mTranslation = getTranslation(mCurrView);
280f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                    if (mLongPressListener != null) {
281f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                        if (mWatchLongPress == null) {
282f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                            mWatchLongPress = new Runnable() {
283f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                                @Override
284f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                                public void run() {
285197823da52a44422890667e21c17c28ab76e64b7Selim Cinek                                    if (mCurrView != null && !mLongPressSent) {
286f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                                        mLongPressSent = true;
2874247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                                        mCurrView.sendAccessibilityEvent(
2884247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                                                AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
2894247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                                        mCurrView.getLocationOnScreen(mTmpPos);
2904247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                                        final int x = (int) ev.getRawX() - mTmpPos[0];
2914247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                                        final int y = (int) ev.getRawY() - mTmpPos[1];
29295d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                                        MenuItem menuItem = null;
29395d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                                        if (mCurrView instanceof ExpandableNotificationRow) {
29495d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                                            menuItem = ((ExpandableNotificationRow) mCurrView)
29595d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                                                    .getProvider().getLongpressMenuItem(mContext);
29695d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                                        }
29795d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                                        mLongPressListener.onLongPress(mCurrView, x, y, menuItem);
298f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                                    }
299f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                                }
300f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                            };
301f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                        }
302469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler                        mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);
303f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                    }
30421ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka                }
30507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                break;
306f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler
30707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_MOVE:
308f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                if (mCurrView != null && !mLongPressSent) {
30907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    mVelocityTracker.addMovement(ev);
31007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    float pos = getPos(ev);
3119b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi                    float perpendicularPos = getPerpendicularPos(ev);
31207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    float delta = pos - mInitialTouchPos;
3139b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi                    float deltaPerpendicular = perpendicularPos - mPerpendicularInitialTouchPos;
3149b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi                    if (Math.abs(delta) > mPagingTouchSlop
3159b0a2c921a9268b89f3e72866b0f011749454c71Jorim Jaggi                            && Math.abs(delta) > Math.abs(deltaPerpendicular)) {
31607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        mCallback.onBeginDrag(mCurrView);
31707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        mDragging = true;
3184b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                        mInitialTouchPos = getPos(ev);
3194b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                        mTranslation = getTranslation(mCurrView);
320f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                        removeLongPressCallback();
32107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    }
32207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                }
32307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                break;
324f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler
32507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_UP:
32668ebcdf3fd8b98fe35ec3e0b2e91fd254fcd807fJeff Brown            case MotionEvent.ACTION_CANCEL:
3274247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                final boolean captured = (mDragging || mLongPressSent);
32807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                mDragging = false;
32907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                mCurrView = null;
330f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler                mLongPressSent = false;
331491d3a9bfab844bf8587545bb1cdab76d2cd4b96Daniel Sandler                removeLongPressCallback();
3324247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler                if (captured) return true;
33307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                break;
33407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
3354247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler        return mDragging || mLongPressSent;
33607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
33707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
3382f2022afa1eb85018368398bd150e9575fc099c9Chet Haase    /**
3392f2022afa1eb85018368398bd150e9575fc099c9Chet Haase     * @param view The view to be dismissed
3402f2022afa1eb85018368398bd150e9575fc099c9Chet Haase     * @param velocity The desired pixels/second speed at which the view should move
341dc6c97df483fb353ff6e18eb9ed59870c1101be8Mady Mellor     * @param useAccelerateInterpolator Should an accelerating Interpolator be used
3422f2022afa1eb85018368398bd150e9575fc099c9Chet Haase     */
343dc6c97df483fb353ff6e18eb9ed59870c1101be8Mady Mellor    public void dismissChild(final View view, float velocity, boolean useAccelerateInterpolator) {
344287963146c96a4cd2772cfee829ac4a4a03c1ff7Mady Mellor        dismissChild(view, velocity, null /* endAction */, 0 /* delay */,
3459c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor                useAccelerateInterpolator, 0 /* fixedDuration */, false /* isDismissAll */);
346eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler    }
347eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler
348eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler    /**
349eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     * @param view The view to be dismissed
350eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     * @param velocity The desired pixels/second speed at which the view should move
351eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     * @param endAction The action to perform at the end
352eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     * @param delay The delay after which we should start
353eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     * @param useAccelerateInterpolator Should an accelerating Interpolator be used
354eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     * @param fixedDuration If not 0, this exact duration will be taken
355eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler     */
3564b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    public void dismissChild(final View animView, float velocity, final Runnable endAction,
3579c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor            long delay, boolean useAccelerateInterpolator, long fixedDuration,
3589c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor            boolean isDismissAll) {
3594b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
36007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        float newPos;
3614b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
362c6461ca5a0892d9b5a47649d49af69165e05b87fMichael Jurka
3639c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor        // if we use the Menu to dismiss an item in landscape, animate up
3649c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor        boolean animateUpForMenu = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
3659c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor                && mSwipeDirection == Y;
3669c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor        // if the language is rtl we prefer swiping to the left
3679c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor        boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
3689c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor                && isLayoutRtl;
3695574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor        boolean animateLeft = (Math.abs(velocity) > getEscapeVelocity() && velocity < 0) ||
3705574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor                (getTranslation(animView) < 0 && !isDismissAll);
3719c2c49634f0d457c1ab79772d3e817df629933dfMady Mellor        if (animateLeft || animateLeftForRtl || animateUpForMenu) {
37207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            newPos = -getSize(animView);
37307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        } else {
37407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            newPos = getSize(animView);
37507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
376eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        long duration;
377eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        if (fixedDuration == 0) {
378eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler            duration = MAX_ESCAPE_ANIMATION_DURATION;
379eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler            if (velocity != 0) {
380eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                duration = Math.min(duration,
381eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                        (int) (Math.abs(newPos - getTranslation(animView)) * 1000f / Math
382eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                                .abs(velocity))
383eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                );
384eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler            } else {
385eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
386eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler            }
3870e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka        } else {
388eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler            duration = fixedDuration;
38907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
3900e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka
391671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson        if (!mDisableHwLayers) {
392671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson            animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
393671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson        }
3944b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
39543c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor            @Override
3964b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor            public void onAnimationUpdate(ValueAnimator animation) {
3974b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
3984b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor            }
3994b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        };
4004b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
4014b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
40234958fa272c9216db4002546c3efad692b3d7775Mady Mellor        if (anim == null) {
40334958fa272c9216db4002546c3efad692b3d7775Mady Mellor            return;
40434958fa272c9216db4002546c3efad692b3d7775Mady Mellor        }
405eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        if (useAccelerateInterpolator) {
406c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek            anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
407287963146c96a4cd2772cfee829ac4a4a03c1ff7Mady Mellor            anim.setDuration(duration);
408eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        } else {
409287963146c96a4cd2772cfee829ac4a4a03c1ff7Mady Mellor            mFlingAnimationUtils.applyDismissing(anim, getTranslation(animView),
410287963146c96a4cd2772cfee829ac4a4a03c1ff7Mady Mellor                    newPos, velocity, getSize(animView));
411eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        }
412eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        if (delay > 0) {
413eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler            anim.setStartDelay(delay);
414eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler        }
4152f2022afa1eb85018368398bd150e9575fc099c9Chet Haase        anim.addListener(new AnimatorListenerAdapter() {
41630637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            private boolean mCancelled;
41730637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
41843c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor            @Override
41930637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            public void onAnimationCancel(Animator animation) {
42030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                mCancelled = true;
42130637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            }
42230637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
42343c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor            @Override
42407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            public void onAnimationEnd(Animator animation) {
4254b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                updateSwipeProgressFromOffset(animView, canBeDismissed);
42630637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                mDismissPendingMap.remove(animView);
42730637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                if (!mCancelled) {
42830637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                    mCallback.onChildDismissed(animView);
42930637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                }
430eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                if (endAction != null) {
431eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                    endAction.run();
432eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler                }
433671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                if (!mDisableHwLayers) {
434671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                    animView.setLayerType(View.LAYER_TYPE_NONE, null);
435671e8f91aae080dc66a0136ce1fc1c1ae0a90db4Winson                }
43607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            }
43707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        });
43830637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
4398aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson        prepareDismissAnimation(animView, anim);
44030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        mDismissPendingMap.put(animView, anim);
44107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        anim.start();
44207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
44307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
4448aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson    /**
4458aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson     * Called to update the dismiss animation.
4468aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson     */
4478aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson    protected void prepareDismissAnimation(View view, Animator anim) {
4488aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson        // Do nothing
4498aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson    }
4508aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson
4514b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    public void snapChild(final View animView, final float targetLeft, float velocity) {
4524b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
4534b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
45443c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor            @Override
45507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            public void onAnimationUpdate(ValueAnimator animation) {
4564b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
45767b03701b633c293fd960435cd97fc0835e44568Michael Jurka            }
4584b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        };
4594b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
4604b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener);
46134958fa272c9216db4002546c3efad692b3d7775Mady Mellor        if (anim == null) {
46234958fa272c9216db4002546c3efad692b3d7775Mady Mellor            return;
46334958fa272c9216db4002546c3efad692b3d7775Mady Mellor        }
4644b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        int duration = SNAP_ANIM_LEN;
4654b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        anim.setDuration(duration);
46667b03701b633c293fd960435cd97fc0835e44568Michael Jurka        anim.addListener(new AnimatorListenerAdapter() {
4677a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor            boolean wasCancelled = false;
4687a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor
4697a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor            @Override
4707a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor            public void onAnimationCancel(Animator animator) {
4717a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor                wasCancelled = true;
4727a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor            }
4737a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor
47443c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor            @Override
47567b03701b633c293fd960435cd97fc0835e44568Michael Jurka            public void onAnimationEnd(Animator animator) {
47630637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                mSnappingChild = false;
4777a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor                if (!wasCancelled) {
4787a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor                    updateSwipeProgressFromOffset(animView, canBeDismissed);
4797a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor                    mCallback.onChildSnappedBack(animView, targetLeft);
4807a5b2b6d382cd8f9a081989ceab7a63ce9eee4d0Mady Mellor                }
48107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            }
48207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        });
4838aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson        prepareSnapBackAnimation(animView, anim);
48430637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        mSnappingChild = true;
48507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        anim.start();
48607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
48707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
488c5fd350522d9269e6239af818f7261a6ead51570Winson    /**
489c5fd350522d9269e6239af818f7261a6ead51570Winson     * Called to update the snap back animation.
490c5fd350522d9269e6239af818f7261a6ead51570Winson     */
4918aa9959413a06c3d2ff75e0c7be9e3cb7ac7cd2eWinson    protected void prepareSnapBackAnimation(View view, Animator anim) {
492c5fd350522d9269e6239af818f7261a6ead51570Winson        // Do nothing
493c5fd350522d9269e6239af818f7261a6ead51570Winson    }
494c5fd350522d9269e6239af818f7261a6ead51570Winson
4954b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    /**
4964b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     * Called when there's a down event.
4974b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     */
49895d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor    public void onDownUpdate(View currView, MotionEvent ev) {
4994b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        // Do nothing
5004b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    }
5014b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
5024b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    /**
5034b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     * Called on a move event.
5044b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     */
50595d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor    protected void onMoveUpdate(View view, MotionEvent ev, float totalTranslation, float delta) {
5064b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        // Do nothing
5074b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    }
5084b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
5094b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    /**
5104b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     * Called in {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)} when the current
5114b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     * view is being animated to dismiss or snap.
5124b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor     */
5134b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
514bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        updateSwipeProgressFromOffset(animView, canBeDismissed, value);
5154b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor    }
5164b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor
51730637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan    private void snapChildInstantly(final View view) {
51830637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
51930637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        setTranslation(view, 0);
52030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        updateSwipeProgressFromOffset(view, canAnimViewBeDismissed);
52130637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan    }
52230637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
52386889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor    /**
52486889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     * Called when a view is updated to be non-dismissable, if the view was being dismissed before
52586889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     * the update this will handle snapping it back into place.
52686889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     *
52786889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     * @param view the view to snap if necessary.
52886889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     * @param animate whether to animate the snap or not.
52986889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     * @param targetLeft the target to snap to.
53086889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor     */
53186889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor    public void snapChildIfNeeded(final View view, boolean animate, float targetLeft) {
53230637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        if ((mDragging && mCurrView == view) || mSnappingChild) {
53330637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            return;
53430637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        }
53530637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        boolean needToSnap = false;
53630637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        Animator dismissPendingAnim = mDismissPendingMap.get(view);
53730637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        if (dismissPendingAnim != null) {
53830637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            needToSnap = true;
53930637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            dismissPendingAnim.cancel();
54030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        } else if (getTranslation(view) != 0) {
54130637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            needToSnap = true;
54230637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        }
54330637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        if (needToSnap) {
54430637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            if (animate) {
54586889c2d21f4e6c26c7e07a477a9e5c398d5d059Mady Mellor                snapChild(view, targetLeft, 0.0f /* velocity */);
54630637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            } else {
54730637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                snapChildInstantly(view);
54830637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan            }
54930637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan        }
55030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan    }
55130637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan
55243c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor    @Override
55307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    public boolean onTouchEvent(MotionEvent ev) {
554f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler        if (mLongPressSent) {
555f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler            return true;
556f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler        }
557f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler
55807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        if (!mDragging) {
55928f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi            if (mCallback.getChildAtPosition(ev) != null) {
56028f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi
56128f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                // We are dragging directly over a card, make sure that we also catch the gesture
56228f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                // even if nobody else wants the touch event.
56328f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                onInterceptTouchEvent(ev);
56428f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                return true;
56528f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi            } else {
56628f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi
56728f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                // We are not doing anything, make sure the long press callback
56828f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                // is not still ticking like a bomb waiting to go off.
56928f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                removeLongPressCallback();
57028f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi                return false;
57128f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi            }
57207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
57307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
57407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        mVelocityTracker.addMovement(ev);
57507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        final int action = ev.getAction();
57607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        switch (action) {
57707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_OUTSIDE:
57807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_MOVE:
57907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                if (mCurrView != null) {
58007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    float delta = getPos(ev) - mInitialTouchPos;
58119c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek                    float absDelta = Math.abs(delta);
58234cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek                    if (absDelta >= getFalsingThreshold()) {
58319c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek                        mTouchAboveFalsingThreshold = true;
58419c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek                    }
58507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    // don't let items that can't be dismissed be dragged more than
58607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    // maxScrollDistance
58707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
5884b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                        float size = getSize(mCurrView);
5895574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor                        float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
59019c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek                        if (absDelta >= size) {
59107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                            delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
59207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        } else {
59307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                            delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
59407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        }
59507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    }
59667b03701b633c293fd960435cd97fc0835e44568Michael Jurka
5974b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                    setTranslation(mCurrView, mTranslation + delta);
5984b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                    updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed);
59995d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor                    onMoveUpdate(mCurrView, ev, mTranslation + delta, delta);
60007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                }
60107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                break;
60207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_UP:
60307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka            case MotionEvent.ACTION_CANCEL:
6043a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                if (mCurrView == null) {
6053a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                    break;
6063a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                }
6073a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, getMaxVelocity());
6083a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                float velocity = getVelocity(mVelocityTracker);
60907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
6103a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
6113a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor                    if (isDismissGesture(ev)) {
61207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        // flingadingy
613dc6c97df483fb353ff6e18eb9ed59870c1101be8Mady Mellor                        dismissChild(mCurrView, velocity,
614dc6c97df483fb353ff6e18eb9ed59870c1101be8Mady Mellor                                !swipedFastEnough() /* useAccelerateInterpolator */);
61507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    } else {
61607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                        // snappity
617622a97646d316ca753c577752ac9010415e9a472Peter Ng                        mCallback.onDragCancelled(mCurrView);
6184b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor                        snapChild(mCurrView, 0 /* leftTarget */, velocity);
61907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                    }
62030637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                    mCurrView = null;
62107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                }
62230637e41c9497576fa644c5ac0bf0864d3a52c5fdongwan                mDragging = false;
62307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka                break;
62407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        }
62507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        return true;
62607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
62707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
62834cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek    private int getFalsingThreshold() {
62934cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek        float factor = mCallback.getFalsingThresholdFactor();
63034cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek        return (int) (mFalsingThreshold * factor);
63134cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek    }
63234cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek
6333a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    private float getMaxVelocity() {
6343a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        return MAX_DISMISS_VELOCITY * mDensityScale;
6353a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    }
6363a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor
6373a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    protected float getEscapeVelocity() {
638bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        return getUnscaledEscapeVelocity() * mDensityScale;
639bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    }
640bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson
641bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    protected float getUnscaledEscapeVelocity() {
642bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        return SWIPE_ESCAPE_VELOCITY;
643bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    }
644bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson
645bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson    protected long getMaxEscapeAnimDuration() {
646bde852dbf5ba8c423da85aedfe6012ca67ee497cWinson        return MAX_ESCAPE_ANIMATION_DURATION;
6473a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    }
6483a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor
6493a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    protected boolean swipedFarEnough() {
6503a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        float translation = getTranslation(mCurrView);
6515574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor        return DISMISS_IF_SWIPED_FAR_ENOUGH
6525574425c32c75825004471434e0cd2fccdd4e5c0Mady Mellor                && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(mCurrView);
6533a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    }
6543a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor
65595d743c38c919dd500d9dcacf9f998500d403d9eMady Mellor    public boolean isDismissGesture(MotionEvent ev) {
656bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor        return ev.getActionMasked() == MotionEvent.ACTION_UP
657bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor                && !isFalseGesture(ev) && (swipedFastEnough() || swipedFarEnough())
658bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor                && mCallback.canChildBeDismissed(mCurrView);
659bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor    }
660bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor
661bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor    public boolean isFalseGesture(MotionEvent ev) {
6623a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        boolean falsingDetected = mCallback.isAntiFalsingNeeded();
6633a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        if (mFalsingManager.isClassiferEnabled()) {
6643a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor            falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
6653a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        } else {
6663a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor            falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
6673a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        }
668bd707492a2ef3641a9e9a64ef72b3b031dac0bb6Mady Mellor        return falsingDetected;
6693a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    }
6703a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor
6713a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    protected boolean swipedFastEnough() {
6723a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        float velocity = getVelocity(mVelocityTracker);
6733a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        float translation = getTranslation(mCurrView);
674dc6c97df483fb353ff6e18eb9ed59870c1101be8Mady Mellor        boolean ret = (Math.abs(velocity) > getEscapeVelocity())
675dc6c97df483fb353ff6e18eb9ed59870c1101be8Mady Mellor                && (velocity > 0) == (translation > 0);
6763a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        return ret;
6773a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    }
6783a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor
6793a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    protected boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
6803a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor            float translation) {
6813a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor        return false;
6823a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor    }
6833a5e8dd820ec6e85121857a03fe9c6a081455f43Mady Mellor
68407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    public interface Callback {
68507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        View getChildAtPosition(MotionEvent ev);
68607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
68707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        boolean canChildBeDismissed(View v);
68807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
68919c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek        boolean isAntiFalsingNeeded();
69019c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek
69107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        void onBeginDrag(View v);
69207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka
69307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka        void onChildDismissed(View v);
694622a97646d316ca753c577752ac9010415e9a472Peter Ng
695622a97646d316ca753c577752ac9010415e9a472Peter Ng        void onDragCancelled(View v);
696eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek
6974b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        /**
6984b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor         * Called when the child is snapped to a position.
6994b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor         *
7004b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor         * @param animView the view that was snapped.
7014b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor         * @param targetLeft the left position the view was snapped to.
7024b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor         */
7034b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor        void onChildSnappedBack(View animView, float targetLeft);
7045d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos
7055d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos        /**
7065d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos         * Updates the swipe progress on a child.
7075d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos         *
7085d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos         * @return if true, prevents the default alpha fading.
7095d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos         */
7105d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos        boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress);
71134cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek
71234cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek        /**
71334cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek         * @return The factor the falsing threshold should be multiplied with
71434cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek         */
71534cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek        float getFalsingThresholdFactor();
71607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka    }
7174247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler
7184247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    /**
7194247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler     * Equivalent to View.OnLongClickListener with coordinates
7204247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler     */
7214247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    public interface LongPressListener {
7224247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler        /**
7234247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler         * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates
7244247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler         * @return whether the longpress was handled
7254247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler         */
72643c2cd1a4071e152e9f4aa9044b03a29cd5ada31Mady Mellor        boolean onLongPress(View v, int x, int y, MenuItem item);
7274247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler    }
72807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka}
729