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; 33eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandlerimport android.view.animation.AnimationUtils; 34eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandlerimport android.view.animation.Interpolator; 35de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport android.view.animation.LinearInterpolator; 3607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 376a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerpublic class SwipeHelper implements Gefingerpoken { 3807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka static final String TAG = "com.android.systemui.SwipeHelper"; 3996f4818ef41141649337d4dee09f837594e93d09Daniel Sandler private static final boolean DEBUG = false; 4007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private static final boolean DEBUG_INVALIDATE = false; 4107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private static final boolean SLOW_ANIMATIONS = false; // DEBUG; 423cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private static final boolean CONSTRAIN_SWIPE = true; 433cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private static final boolean FADE_OUT_DURING_SWIPE = true; 443cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; 4507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 4607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public static final int X = 0; 4707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public static final int Y = 1; 4807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 492f2022afa1eb85018368398bd150e9575fc099c9Chet Haase private static LinearInterpolator sLinearInterpolator = new LinearInterpolator(); 50eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler private final Interpolator mFastOutLinearInInterpolator; 512f2022afa1eb85018368398bd150e9575fc099c9Chet Haase 5207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec 530e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms 540e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms 550e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka private int MAX_DISMISS_VELOCITY = 2000; // dp/sec 560e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 150; // ms 5707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 585d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos public static float SWIPE_PROGRESS_FADE_START = 0f; // fraction of thumbnail width 5907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka // where fade starts 605d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos static final float SWIPE_PROGRESS_FADE_END = 0.5f; // fraction of thumbnail width 615d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos // beyond which swipe progress->0 625d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos private float mMinSwipeProgress = 0f; 635d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos private float mMaxSwipeProgress = 1f; 6407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 6507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float mPagingTouchSlop; 6607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private Callback mCallback; 67f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler private Handler mHandler; 6807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private int mSwipeDirection; 6907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private VelocityTracker mVelocityTracker; 7007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 7107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float mInitialTouchPos; 7207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private boolean mDragging; 7307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private View mCurrView; 743cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private View mCurrAnimView; 753cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private boolean mCanCurrViewBeDimissed; 7607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float mDensityScale; 7707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 78f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler private boolean mLongPressSent; 794247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler private LongPressListener mLongPressListener; 80f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler private Runnable mWatchLongPress; 81469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler private long mLongPressTimeout; 82f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 834247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler final private int[] mTmpPos = new int[2]; 8419c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek private int mFalsingThreshold; 8519c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek private boolean mTouchAboveFalsingThreshold; 864247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler 87eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler public SwipeHelper(int swipeDirection, Callback callback, Context context) { 8807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mCallback = callback; 89f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mHandler = new Handler(); 9007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mSwipeDirection = swipeDirection; 9107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mVelocityTracker = VelocityTracker.obtain(); 92eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler mDensityScale = context.getResources().getDisplayMetrics().density; 93eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler mPagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop(); 94469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler 95469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler mLongPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f); // extra long-press! 96eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, 97eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler android.R.interpolator.fast_out_linear_in); 9819c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mFalsingThreshold = context.getResources().getDimensionPixelSize( 9919c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek R.dimen.swipe_helper_falsing_threshold); 10007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 10107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 1024247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler public void setLongPressListener(LongPressListener listener) { 103f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mLongPressListener = listener; 104f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 105f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 10607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void setDensityScale(float densityScale) { 10707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mDensityScale = densityScale; 10807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 10907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 11007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void setPagingTouchSlop(float pagingTouchSlop) { 11107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mPagingTouchSlop = pagingTouchSlop; 11207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 11307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 11407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float getPos(MotionEvent ev) { 11507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return mSwipeDirection == X ? ev.getX() : ev.getY(); 11607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 11707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 1183cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private float getTranslation(View v) { 1193cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY(); 12007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 12107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 12207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float getVelocity(VelocityTracker vt) { 12307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return mSwipeDirection == X ? vt.getXVelocity() : 12407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka vt.getYVelocity(); 12507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 12607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 12707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private ObjectAnimator createTranslationAnimation(View v, float newPos) { 12807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka ObjectAnimator anim = ObjectAnimator.ofFloat(v, 12907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mSwipeDirection == X ? "translationX" : "translationY", newPos); 13007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return anim; 13107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 13207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 13307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float getPerpendicularVelocity(VelocityTracker vt) { 13407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return mSwipeDirection == X ? vt.getYVelocity() : 13507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka vt.getXVelocity(); 13607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 13707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 13807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private void setTranslation(View v, float translate) { 13907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (mSwipeDirection == X) { 14007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka v.setTranslationX(translate); 14107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } else { 14207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka v.setTranslationY(translate); 14307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 14407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 14507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 14607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private float getSize(View v) { 14707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return mSwipeDirection == X ? v.getMeasuredWidth() : 14807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka v.getMeasuredHeight(); 14907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 15007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 1515d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos public void setMinSwipeProgress(float minSwipeProgress) { 1525d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos mMinSwipeProgress = minSwipeProgress; 1534eaa983f253d0215d4de777edd8616318610ea22Michael Jurka } 1544eaa983f253d0215d4de777edd8616318610ea22Michael Jurka 1555d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos public void setMaxSwipeProgress(float maxSwipeProgress) { 1565d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos mMaxSwipeProgress = maxSwipeProgress; 157de61fd7822ea15fb691405c1aae472caa58e83baAdrian Roos } 158de61fd7822ea15fb691405c1aae472caa58e83baAdrian Roos 1595d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos private float getSwipeProgressForOffset(View view) { 1603cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float viewSize = getSize(view); 1615d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos final float fadeSize = SWIPE_PROGRESS_FADE_END * viewSize; 16207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float result = 1.0f; 1633cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float pos = getTranslation(view); 1645d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos if (pos >= viewSize * SWIPE_PROGRESS_FADE_START) { 1655d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos result = 1.0f - (pos - viewSize * SWIPE_PROGRESS_FADE_START) / fadeSize; 1665d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos } else if (pos < viewSize * (1.0f - SWIPE_PROGRESS_FADE_START)) { 1675d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos result = 1.0f + (viewSize * SWIPE_PROGRESS_FADE_START + pos) / fadeSize; 16807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 1695d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos return Math.min(Math.max(mMinSwipeProgress, result), mMaxSwipeProgress); 17007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 17107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 1725d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos private void updateSwipeProgressFromOffset(View animView, boolean dismissable) { 1735d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos float swipeProgress = getSwipeProgressForOffset(animView); 1745d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos if (!mCallback.updateSwipeProgress(animView, dismissable, swipeProgress)) { 1755d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos if (FADE_OUT_DURING_SWIPE && dismissable) { 1765d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos float alpha = swipeProgress; 1775d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos if (alpha != 0f && alpha != 1f) { 1785d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 1795d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos } else { 1805d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos animView.setLayerType(View.LAYER_TYPE_NONE, null); 1815d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos } 1825d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos animView.setAlpha(getSwipeProgressForOffset(animView)); 183499293f096ef3182ef39e42cc06284501022b5cfMichael Jurka } 18467b03701b633c293fd960435cd97fc0835e44568Michael Jurka } 18567b03701b633c293fd960435cd97fc0835e44568Michael Jurka invalidateGlobalRegion(animView); 18667b03701b633c293fd960435cd97fc0835e44568Michael Jurka } 18767b03701b633c293fd960435cd97fc0835e44568Michael Jurka 188a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler // invalidate the view's own bounds all the way up the view hierarchy 189a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler public static void invalidateGlobalRegion(View view) { 190a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler invalidateGlobalRegion( 191a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler view, 192a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom())); 193a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler } 194a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler 195a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler // invalidate a rectangle relative to the view's coordinate system all the way up the view 196a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler // hierarchy 197a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler public static void invalidateGlobalRegion(View view, RectF childBounds) { 19896f4818ef41141649337d4dee09f837594e93d09Daniel Sandler //childBounds.offset(view.getTranslationX(), view.getTranslationY()); 19907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (DEBUG_INVALIDATE) 20007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka Log.v(TAG, "-------------"); 20107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka while (view.getParent() != null && view.getParent() instanceof View) { 20207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka view = (View) view.getParent(); 20307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka view.getMatrix().mapRect(childBounds); 20407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka view.invalidate((int) Math.floor(childBounds.left), 20507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka (int) Math.floor(childBounds.top), 20607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka (int) Math.ceil(childBounds.right), 20707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka (int) Math.ceil(childBounds.bottom)); 20807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (DEBUG_INVALIDATE) { 20907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) 21007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka + "," + (int) Math.floor(childBounds.top) 21107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka + "," + (int) Math.ceil(childBounds.right) 21207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka + "," + (int) Math.ceil(childBounds.bottom)); 21307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 21407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 21507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 21607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 217469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler public void removeLongPressCallback() { 218f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler if (mWatchLongPress != null) { 219f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mHandler.removeCallbacks(mWatchLongPress); 220491d3a9bfab844bf8587545bb1cdab76d2cd4b96Daniel Sandler mWatchLongPress = null; 221f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 222f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 223f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 2244247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler public boolean onInterceptTouchEvent(final MotionEvent ev) { 22507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka final int action = ev.getAction(); 22607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 22707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka switch (action) { 22807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_DOWN: 22919c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mTouchAboveFalsingThreshold = false; 23007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mDragging = false; 231f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mLongPressSent = false; 23207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mCurrView = mCallback.getChildAtPosition(ev); 23307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mVelocityTracker.clear(); 23421ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka if (mCurrView != null) { 23521ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka mCurrAnimView = mCallback.getChildContentView(mCurrView); 23621ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); 23721ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka mVelocityTracker.addMovement(ev); 23821ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka mInitialTouchPos = getPos(ev); 239f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 240f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler if (mLongPressListener != null) { 241f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler if (mWatchLongPress == null) { 242f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mWatchLongPress = new Runnable() { 243f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler @Override 244f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler public void run() { 245f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler if (mCurrView != null && !mLongPressSent) { 246f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mLongPressSent = true; 2474247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler mCurrView.sendAccessibilityEvent( 2484247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 2494247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler mCurrView.getLocationOnScreen(mTmpPos); 2504247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler final int x = (int) ev.getRawX() - mTmpPos[0]; 2514247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler final int y = (int) ev.getRawY() - mTmpPos[1]; 2524247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler mLongPressListener.onLongPress(mCurrView, x, y); 253f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 254f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 255f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler }; 256f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 257469e96e206f8df44b32ce393f8d19f0cae730030Daniel Sandler mHandler.postDelayed(mWatchLongPress, mLongPressTimeout); 258f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 259f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 26021ce2d8caeda3c9eb762a2129d37c384de718941Michael Jurka } 26107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka break; 262f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 26307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_MOVE: 264f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler if (mCurrView != null && !mLongPressSent) { 26507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mVelocityTracker.addMovement(ev); 26607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float pos = getPos(ev); 26707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float delta = pos - mInitialTouchPos; 26807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (Math.abs(delta) > mPagingTouchSlop) { 26907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mCallback.onBeginDrag(mCurrView); 27007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mDragging = true; 2713cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView); 272f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 273f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler removeLongPressCallback(); 27407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 27507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 276f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 27707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka break; 278f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 27907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_UP: 28068ebcdf3fd8b98fe35ec3e0b2e91fd254fcd807fJeff Brown case MotionEvent.ACTION_CANCEL: 2814247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler final boolean captured = (mDragging || mLongPressSent); 28207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mDragging = false; 28307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mCurrView = null; 2843cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mCurrAnimView = null; 285f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler mLongPressSent = false; 286491d3a9bfab844bf8587545bb1cdab76d2cd4b96Daniel Sandler removeLongPressCallback(); 2874247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler if (captured) return true; 28807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka break; 28907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 2904247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler return mDragging || mLongPressSent; 29107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 29207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 2932f2022afa1eb85018368398bd150e9575fc099c9Chet Haase /** 2942f2022afa1eb85018368398bd150e9575fc099c9Chet Haase * @param view The view to be dismissed 2952f2022afa1eb85018368398bd150e9575fc099c9Chet Haase * @param velocity The desired pixels/second speed at which the view should move 2962f2022afa1eb85018368398bd150e9575fc099c9Chet Haase */ 2973cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public void dismissChild(final View view, float velocity) { 298eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler dismissChild(view, velocity, null, 0, false, 0); 299eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } 300eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler 301eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler /** 302eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler * @param view The view to be dismissed 303eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler * @param velocity The desired pixels/second speed at which the view should move 304eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler * @param endAction The action to perform at the end 305eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler * @param delay The delay after which we should start 306eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler * @param useAccelerateInterpolator Should an accelerating Interpolator be used 307eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler * @param fixedDuration If not 0, this exact duration will be taken 308eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler */ 309eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler public void dismissChild(final View view, float velocity, final Runnable endAction, 310eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler long delay, boolean useAccelerateInterpolator, long fixedDuration) { 3113cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka final View animView = mCallback.getChildContentView(view); 3123cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 31307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float newPos; 314c6461ca5a0892d9b5a47649d49af69165e05b87fMichael Jurka 315c6461ca5a0892d9b5a47649d49af69165e05b87fMichael Jurka if (velocity < 0 316c6461ca5a0892d9b5a47649d49af69165e05b87fMichael Jurka || (velocity == 0 && getTranslation(animView) < 0) 317c6461ca5a0892d9b5a47649d49af69165e05b87fMichael Jurka // if we use the Menu to dismiss an item in landscape, animate up 318c6461ca5a0892d9b5a47649d49af69165e05b87fMichael Jurka || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)) { 31907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka newPos = -getSize(animView); 32007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } else { 32107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka newPos = getSize(animView); 32207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 323eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler long duration; 324eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler if (fixedDuration == 0) { 325eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler duration = MAX_ESCAPE_ANIMATION_DURATION; 326eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler if (velocity != 0) { 327eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler duration = Math.min(duration, 328eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler (int) (Math.abs(newPos - getTranslation(animView)) * 1000f / Math 329eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler .abs(velocity)) 330eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler ); 331eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } else { 332eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler duration = DEFAULT_ESCAPE_ANIMATION_DURATION; 333eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } 3340e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka } else { 335eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler duration = fixedDuration; 33607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 3370e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka 3382f2022afa1eb85018368398bd150e9575fc099c9Chet Haase animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 33907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka ObjectAnimator anim = createTranslationAnimation(animView, newPos); 340eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler if (useAccelerateInterpolator) { 341eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler anim.setInterpolator(mFastOutLinearInInterpolator); 342eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } else { 343eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler anim.setInterpolator(sLinearInterpolator); 344eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } 34507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka anim.setDuration(duration); 346eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler if (delay > 0) { 347eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler anim.setStartDelay(delay); 348eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } 3492f2022afa1eb85018368398bd150e9575fc099c9Chet Haase anim.addListener(new AnimatorListenerAdapter() { 35007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void onAnimationEnd(Animator animation) { 3513cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mCallback.onChildDismissed(view); 352eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler if (endAction != null) { 353eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler endAction.run(); 354eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler } 3552f2022afa1eb85018368398bd150e9575fc099c9Chet Haase animView.setLayerType(View.LAYER_TYPE_NONE, null); 35607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 35707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka }); 35807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka anim.addUpdateListener(new AnimatorUpdateListener() { 35907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void onAnimationUpdate(ValueAnimator animation) { 3605d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); 36107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 36207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka }); 36307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka anim.start(); 36407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 36507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 3663cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public void snapChild(final View view, float velocity) { 3673cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka final View animView = mCallback.getChildContentView(view); 3683cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView); 36907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka ObjectAnimator anim = createTranslationAnimation(animView, 0); 37007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka int duration = SNAP_ANIM_LEN; 37107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka anim.setDuration(duration); 37207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka anim.addUpdateListener(new AnimatorUpdateListener() { 37307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void onAnimationUpdate(ValueAnimator animation) { 3745d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); 37567b03701b633c293fd960435cd97fc0835e44568Michael Jurka } 37667b03701b633c293fd960435cd97fc0835e44568Michael Jurka }); 37767b03701b633c293fd960435cd97fc0835e44568Michael Jurka anim.addListener(new AnimatorListenerAdapter() { 37867b03701b633c293fd960435cd97fc0835e44568Michael Jurka public void onAnimationEnd(Animator animator) { 3795d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed); 380eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek mCallback.onChildSnappedBack(animView); 38107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 38207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka }); 38307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka anim.start(); 38407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 38507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 38607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public boolean onTouchEvent(MotionEvent ev) { 387f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler if (mLongPressSent) { 388f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler return true; 389f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler } 390f7a1956b06faeb6025fdea331f81d66edda58b3cDaniel Sandler 39107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (!mDragging) { 39228f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi if (mCallback.getChildAtPosition(ev) != null) { 39328f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi 39428f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi // We are dragging directly over a card, make sure that we also catch the gesture 39528f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi // even if nobody else wants the touch event. 39628f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi onInterceptTouchEvent(ev); 39728f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi return true; 39828f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi } else { 39928f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi 40028f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi // We are not doing anything, make sure the long press callback 40128f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi // is not still ticking like a bomb waiting to go off. 40228f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi removeLongPressCallback(); 40328f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi return false; 40428f0e5932944d9abc4b6879b1d05523e9341c385Jorim Jaggi } 40507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 40607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 40707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mVelocityTracker.addMovement(ev); 40807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka final int action = ev.getAction(); 40907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka switch (action) { 41007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_OUTSIDE: 41107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_MOVE: 41207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (mCurrView != null) { 41307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float delta = getPos(ev) - mInitialTouchPos; 41419c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek float absDelta = Math.abs(delta); 41534cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek if (absDelta >= getFalsingThreshold()) { 41619c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mTouchAboveFalsingThreshold = true; 41719c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek } 41807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka // don't let items that can't be dismissed be dragged more than 41907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka // maxScrollDistance 42007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { 4213cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float size = getSize(mCurrAnimView); 42207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float maxScrollDistance = 0.15f * size; 42319c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek if (absDelta >= size) { 42407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka delta = delta > 0 ? maxScrollDistance : -maxScrollDistance; 42507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } else { 42607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2)); 42707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 42807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 4293cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka setTranslation(mCurrAnimView, delta); 43067b03701b633c293fd960435cd97fc0835e44568Michael Jurka 4315d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos updateSwipeProgressFromOffset(mCurrAnimView, mCanCurrViewBeDimissed); 43207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 43307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka break; 43407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_UP: 43507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka case MotionEvent.ACTION_CANCEL: 43607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (mCurrView != null) { 4370761e4cd95b6968dd4b1659a766ef504d13f6d50Daniel Sandler float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale; 43807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity); 43907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale; 44007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float velocity = getVelocity(mVelocityTracker); 44107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); 44207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 44307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka // Decide whether to dismiss the current view 44407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH && 4453cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka Math.abs(getTranslation(mCurrAnimView)) > 0.4 * getSize(mCurrAnimView); 44607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) && 44707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka (Math.abs(velocity) > Math.abs(perpendicularVelocity)) && 4483cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka (velocity > 0) == (getTranslation(mCurrAnimView) > 0); 44919c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek boolean falsingDetected = mCallback.isAntiFalsingNeeded() 45019c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek && !mTouchAboveFalsingThreshold; 45107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 45219c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) 45319c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek && !falsingDetected && (childSwipedFastEnough || childSwipedFarEnough); 45407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 45507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (dismissChild) { 45607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka // flingadingy 45707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f); 45807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } else { 45907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka // snappity 460622a97646d316ca753c577752ac9010415e9a472Peter Ng mCallback.onDragCancelled(mCurrView); 46107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka snapChild(mCurrView, velocity); 46207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 46307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 46407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka break; 46507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 46607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return true; 46707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 46807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 46934cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek private int getFalsingThreshold() { 47034cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek float factor = mCallback.getFalsingThresholdFactor(); 47134cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek return (int) (mFalsingThreshold * factor); 47234cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek } 47334cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek 47407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public interface Callback { 47507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka View getChildAtPosition(MotionEvent ev); 47607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 47707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka View getChildContentView(View v); 47807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 47907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka boolean canChildBeDismissed(View v); 48007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 48119c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek boolean isAntiFalsingNeeded(); 48219c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek 48307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka void onBeginDrag(View v); 48407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 48507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka void onChildDismissed(View v); 486622a97646d316ca753c577752ac9010415e9a472Peter Ng 487622a97646d316ca753c577752ac9010415e9a472Peter Ng void onDragCancelled(View v); 488eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek 489eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek void onChildSnappedBack(View animView); 4905d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos 4915d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos /** 4925d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos * Updates the swipe progress on a child. 4935d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos * 4945d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos * @return if true, prevents the default alpha fading. 4955d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos */ 4965d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress); 49734cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek 49834cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek /** 49934cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek * @return The factor the falsing threshold should be multiplied with 50034cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek */ 50134cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek float getFalsingThresholdFactor(); 50207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 5034247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler 5044247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler /** 5054247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler * Equivalent to View.OnLongClickListener with coordinates 5064247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler */ 5074247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler public interface LongPressListener { 5084247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler /** 5094247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates 5104247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler * @return whether the longpress was handled 5114247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler */ 5124247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler boolean onLongPress(View v, int x, int y); 5134247a5c16237705c470b4dd7378a657c5f7b6d51Dan Sandler } 51407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka} 515