1f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira/* 2f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Copyright (C) 2012 Google Inc. 3f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Licensed to The Android Open Source Project. 4f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * 5f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 6f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * you may not use this file except in compliance with the License. 7f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * You may obtain a copy of the License at 8f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * 9f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 10f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * 11f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Unless required by applicable law or agreed to in writing, software 12f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 13f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * See the License for the specific language governing permissions and 15f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * limitations under the License. 16f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira */ 17f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 18f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereirapackage com.android.mail.ui; 19f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 20f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.animation.Animator; 21f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.animation.AnimatorListenerAdapter; 22f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.animation.ObjectAnimator; 23f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.animation.ValueAnimator; 24f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.animation.ValueAnimator.AnimatorUpdateListener; 256f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereiraimport android.content.Context; 266f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereiraimport android.content.res.Resources; 27f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.graphics.RectF; 28f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.MotionEvent; 29f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.VelocityTracker; 30f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.View; 3143e253e6c0ab232e77233ff69374fff86289c4bdmindypimport android.view.animation.DecelerateInterpolator; 32f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 336f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereiraimport com.android.mail.R; 34b184bfe96fa3512af88260fce4f3cee3066fb28dScott Kennedyimport com.android.mail.utils.LogUtils; 35bb6039ed45a5eeccf08d97cb91d1b91069fed5afAndy Huangimport com.android.mail.utils.Utils; 36866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 37f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereirapublic class SwipeHelper { 38f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira static final String TAG = "com.android.systemui.SwipeHelper"; 39f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private static final boolean DEBUG_INVALIDATE = false; 40f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private static final boolean CONSTRAIN_SWIPE = true; 41f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private static final boolean FADE_OUT_DURING_SWIPE = true; 42f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; 43d6020119c71ef9fe38725d0f0291cac7b9df6e79Vikram Aggarwal // Turn on for debugging only during development. 44d6020119c71ef9fe38725d0f0291cac7b9df6e79Vikram Aggarwal private static final boolean LOG_SWIPE_DISMISS_VELOCITY = false; 45f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 46f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public static final int X = 0; 47f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public static final int Y = 1; 48f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 49ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static DecelerateInterpolator sDecelerateInterpolator = 507af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp new DecelerateInterpolator(1.0f); 51f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 526f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira private static int SWIPE_ESCAPE_VELOCITY = -1; 536f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira private static int DEFAULT_ESCAPE_ANIMATION_DURATION; 546f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira private static int MAX_ESCAPE_ANIMATION_DURATION; 556f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira private static int MAX_DISMISS_VELOCITY; 566f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira private static int SNAP_ANIM_LEN; 576f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira private static float MIN_SWIPE; 58f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 59f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public static float ALPHA_FADE_START = 0f; // fraction of thumbnail width 60f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // where fade starts 617af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp public static float ALPHA_TEXT_FADE_START = 0.4f; 621ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira static final float ALPHA_FADE_END = 0.7f; // fraction of thumbnail width 63f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // beyond which alpha->0 646f4af489f6e10c7b576361bf69bcacabc2fb820cMindy Pereira private static final float FACTOR = 1.2f; 65f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 664485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal /* Dead region where swipe cannot be initiated. */ 67b2fe36b5d654eababbeee7f144edb31c4eb83490Alice Yang private final static int DEAD_REGION_FOR_SWIPE = 56; 684485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal 69f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private float mPagingTouchSlop; 702102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final Callback mCallback; 712102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final int mSwipeDirection; 722102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final VelocityTracker mVelocityTracker; 73f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 74cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira private float mInitialTouchPosX; 75f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private boolean mDragging; 766c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private SwipeableItemView mCurrView; 77f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private View mCurrAnimView; 78f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private boolean mCanCurrViewBeDimissed; 79f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private float mDensityScale; 80866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private float mLastY; 81cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira private float mInitialTouchPosY; 827af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp private LeaveBehindItem mPrevView; 83f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 846f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira public SwipeHelper(Context context, int swipeDirection, Callback callback, float densityScale, 856f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira float pagingTouchSlop) { 86f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mCallback = callback; 87f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mSwipeDirection = swipeDirection; 88f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mVelocityTracker = VelocityTracker.obtain(); 89f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mDensityScale = densityScale; 90f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mPagingTouchSlop = pagingTouchSlop; 916f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira if (SWIPE_ESCAPE_VELOCITY == -1) { 926f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira Resources res = context.getResources(); 936f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira SWIPE_ESCAPE_VELOCITY = res.getInteger(R.integer.swipe_escape_velocity); 946f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira DEFAULT_ESCAPE_ANIMATION_DURATION = res.getInteger(R.integer.escape_animation_duration); 956f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira MAX_ESCAPE_ANIMATION_DURATION = res.getInteger(R.integer.max_escape_animation_duration); 966f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira MAX_DISMISS_VELOCITY = res.getInteger(R.integer.max_dismiss_velocity); 976f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira SNAP_ANIM_LEN = res.getInteger(R.integer.snap_animation_duration); 986f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira MIN_SWIPE = res.getDimension(R.dimen.min_swipe); 996f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira } 100f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 101f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 102f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public void setDensityScale(float densityScale) { 103f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mDensityScale = densityScale; 104f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 105f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 106f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public void setPagingTouchSlop(float pagingTouchSlop) { 107f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mPagingTouchSlop = pagingTouchSlop; 108f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 109f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 110f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private float getVelocity(VelocityTracker vt) { 111f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return mSwipeDirection == X ? vt.getXVelocity() : 112f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira vt.getYVelocity(); 113f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 114f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 115f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private ObjectAnimator createTranslationAnimation(View v, float newPos) { 116f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira ObjectAnimator anim = ObjectAnimator.ofFloat(v, 117f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mSwipeDirection == X ? "translationX" : "translationY", newPos); 118f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return anim; 119f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 120f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 121866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private ObjectAnimator createDismissAnimation(View v, float newPos, int duration) { 122866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira ObjectAnimator anim = createTranslationAnimation(v, newPos); 12343e253e6c0ab232e77233ff69374fff86289c4bdmindyp anim.setInterpolator(sDecelerateInterpolator); 124866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira anim.setDuration(duration); 125866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return anim; 126866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 127866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 128f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private float getPerpendicularVelocity(VelocityTracker vt) { 129f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return mSwipeDirection == X ? vt.getYVelocity() : 130f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira vt.getXVelocity(); 131f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 132f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 133f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private void setTranslation(View v, float translate) { 134f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (mSwipeDirection == X) { 135f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira v.setTranslationX(translate); 136f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } else { 137f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira v.setTranslationY(translate); 138f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 139f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 140f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 141f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private float getSize(View v) { 142f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return mSwipeDirection == X ? v.getMeasuredWidth() : 143f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira v.getMeasuredHeight(); 144f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 145f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 146f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira private float getAlphaForOffset(View view) { 147f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float viewSize = getSize(view); 148f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira final float fadeSize = ALPHA_FADE_END * viewSize; 149f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float result = 1.0f; 150f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float pos = view.getTranslationX(); 151f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (pos >= viewSize * ALPHA_FADE_START) { 152f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira result = 1.0f - (pos - viewSize * ALPHA_FADE_START) / fadeSize; 153f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } else if (pos < viewSize * (1.0f - ALPHA_FADE_START)) { 154f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira result = 1.0f + (viewSize * ALPHA_FADE_START + pos) / fadeSize; 155f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 156f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal float minAlpha = 0.5f; 157f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal return Math.max(minAlpha, result); 158f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 159f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 1607af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp private float getTextAlphaForOffset(View view) { 1617af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp float viewSize = getSize(view); 1627af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp final float fadeSize = ALPHA_TEXT_FADE_START * viewSize; 1637af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp float result = 1.0f; 1647af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp float pos = view.getTranslationX(); 1657af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp if (pos >= 0) { 1667af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp result = 1.0f - pos / fadeSize; 1677af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } else if (pos < 0) { 1687af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp result = 1.0f + pos / fadeSize; 1697af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 1707af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return Math.max(0, result); 1717af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 1727af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp 173f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // invalidate the view's own bounds all the way up the view hierarchy 174f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public static void invalidateGlobalRegion(View view) { 175f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira invalidateGlobalRegion( 176f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira view, 177f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom())); 178f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 179f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 180f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // invalidate a rectangle relative to the view's coordinate system all the way up the view 181f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // hierarchy 182f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public static void invalidateGlobalRegion(View view, RectF childBounds) { 183f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira //childBounds.offset(view.getTranslationX(), view.getTranslationY()); 184f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (DEBUG_INVALIDATE) 185b184bfe96fa3512af88260fce4f3cee3066fb28dScott Kennedy LogUtils.v(TAG, "-------------"); 186f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira while (view.getParent() != null && view.getParent() instanceof View) { 187f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira view = (View) view.getParent(); 188f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira view.getMatrix().mapRect(childBounds); 189f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira view.invalidate((int) Math.floor(childBounds.left), 190f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira (int) Math.floor(childBounds.top), 191f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira (int) Math.ceil(childBounds.right), 192f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira (int) Math.ceil(childBounds.bottom)); 193f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (DEBUG_INVALIDATE) { 194b184bfe96fa3512af88260fce4f3cee3066fb28dScott Kennedy LogUtils.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) 195f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira + "," + (int) Math.floor(childBounds.top) 196f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira + "," + (int) Math.ceil(childBounds.right) 197f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira + "," + (int) Math.ceil(childBounds.bottom)); 198f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 199f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 200f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 201f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 202f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public boolean onInterceptTouchEvent(MotionEvent ev) { 203f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira final int action = ev.getAction(); 204f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira switch (action) { 205f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_DOWN: 206866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira mLastY = ev.getY(); 207f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mDragging = false; 208f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira View view = mCallback.getChildAtPosition(ev); 2096c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira if (view instanceof SwipeableItemView) { 2106c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira mCurrView = (SwipeableItemView) view; 211f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 212f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mVelocityTracker.clear(); 213f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (mCurrView != null) { 2142102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei mCurrAnimView = mCurrView.getSwipeableView().getView(); 215f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); 216f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mVelocityTracker.addMovement(ev); 217f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira mInitialTouchPosX = ev.getX(); 218cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira mInitialTouchPosY = ev.getY(); 219f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 2203b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mCallback.cancelDismissCounter(); 221f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira break; 222f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_MOVE: 223f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (mCurrView != null) { 224866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira // Check the movement direction. 2254cf76548c08d8447546a5b8a11c2ea5377f91025Mindy Pereira if (mLastY >= 0 && !mDragging) { 226866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira float currY = ev.getY(); 2276f4af489f6e10c7b576361bf69bcacabc2fb820cMindy Pereira float currX = ev.getX(); 2286f4af489f6e10c7b576361bf69bcacabc2fb820cMindy Pereira float deltaY = Math.abs(currY - mInitialTouchPosY); 2296f4af489f6e10c7b576361bf69bcacabc2fb820cMindy Pereira float deltaX = Math.abs(currX - mInitialTouchPosX); 230d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp if (deltaY > mCurrView.getMinAllowScrollDistance() 231d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp && deltaY > (FACTOR * deltaX)) { 232866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira mLastY = ev.getY(); 233d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp mCallback.onScroll(); 234866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return false; 235866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 236866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 237f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mVelocityTracker.addMovement(ev); 238f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float pos = ev.getX(); 239cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira float delta = pos - mInitialTouchPosX; 240f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (Math.abs(delta) > mPagingTouchSlop) { 2412102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei mCallback.onBeginDrag(mCurrView.getSwipeableView().getView()); 2427af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp mPrevView = mCallback.getLastSwipedItem(); 243a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira mDragging = true; 244a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira mInitialTouchPosX = ev.getX() - mCurrAnimView.getTranslationX(); 245a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira mInitialTouchPosY = ev.getY(); 246f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 247f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 248866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira mLastY = ev.getY(); 249f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira break; 250f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_UP: 251f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_CANCEL: 252f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mDragging = false; 253f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mCurrView = null; 254f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mCurrAnimView = null; 255866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira mLastY = -1; 256f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira break; 257f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 258f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return mDragging; 259f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 260f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 261f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira /** 262f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * @param view The view to be dismissed 263866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * @param velocity The desired pixels/second speed at which the view should 264866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * move 265f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira */ 2666c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private void dismissChild(final SwipeableItemView view, float velocity) { 267e1ba1013409486f88f06af2932546a1b366704d3Jin Cao final View animView = view.getSwipeableView().getView(); 2686c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 269866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira float newPos = determinePos(animView, velocity); 270866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira int duration = determineDuration(animView, newPos, velocity); 271f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 272bb6039ed45a5eeccf08d97cb91d1b91069fed5afAndy Huang Utils.enableHardwareLayer(animView); 273866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira ObjectAnimator anim = createDismissAnimation(animView, newPos, duration); 274f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira anim.addListener(new AnimatorListenerAdapter() { 275cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira @Override 276f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public void onAnimationEnd(Animator animation) { 277e1ba1013409486f88f06af2932546a1b366704d3Jin Cao mCallback.onChildDismissed(view); 2786c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira animView.setLayerType(View.LAYER_TYPE_NONE, null); 279f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 280f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira }); 281f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira anim.addUpdateListener(new AnimatorUpdateListener() { 282cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira @Override 283f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public void onAnimationUpdate(ValueAnimator animation) { 284f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { 285f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira animView.setAlpha(getAlphaForOffset(animView)); 286f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 287f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira invalidateGlobalRegion(animView); 288f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 289f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira }); 290f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira anim.start(); 291f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 292f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 293ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static int determineDuration(View animView, float newPos, float velocity) { 294866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira int duration = MAX_ESCAPE_ANIMATION_DURATION; 295866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira if (velocity != 0) { 296866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira duration = Math 297866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira .min(duration, 298f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira (int) (Math.abs(newPos - animView.getTranslationX()) * 1000f / Math 299866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira .abs(velocity))); 300866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } else { 301866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira duration = DEFAULT_ESCAPE_ANIMATION_DURATION; 302866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 303866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return duration; 304866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 305866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 306866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private float determinePos(View animView, float velocity) { 3074485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal final float newPos; 308f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira if (velocity < 0 || (velocity == 0 && animView.getTranslationX() < 0) 309866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira // if we use the Menu to dismiss an item in landscape, animate up 310f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira || (velocity == 0 && animView.getTranslationX() == 0 && mSwipeDirection == Y)) { 311866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira newPos = -getSize(animView); 312866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } else { 313866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira newPos = getSize(animView); 314866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 315866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return newPos; 316866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 317866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 318ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy public void snapChild(final SwipeableItemView view) { 3192102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei final View animView = view.getSwipeableView().getView(); 3206c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 3214485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal final ObjectAnimator anim = createTranslationAnimation(animView, 0); 3224485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal final int duration = SNAP_ANIM_LEN; 323f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira anim.setDuration(duration); 324f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira anim.addUpdateListener(new AnimatorUpdateListener() { 325cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira @Override 326f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public void onAnimationUpdate(ValueAnimator animation) { 327f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { 328f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira animView.setAlpha(getAlphaForOffset(animView)); 329f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 330f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira invalidateGlobalRegion(animView); 331f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 332f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira }); 33328fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira anim.addListener(new Animator.AnimatorListener() { 33428fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira @Override 33528fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira public void onAnimationStart(Animator animation) { 33628fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira } 33728fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira @Override 33828fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira public void onAnimationEnd(Animator animation) { 33928fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira animView.setAlpha(1.0f); 340d592b0bbeb3eb47c5978c861210482a74d85cedaMindy Pereira mCallback.onDragCancelled(mCurrView); 34128fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira } 34228fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira @Override 34328fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira public void onAnimationCancel(Animator animation) { 34428fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira } 34528fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira @Override 34628fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira public void onAnimationRepeat(Animator animation) { 34728fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira } 34828fdaaf04b64f8c4745484e3b3a0894b24f4486aMindy Pereira }); 349f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira anim.start(); 350f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 351f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 352f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public boolean onTouchEvent(MotionEvent ev) { 353f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (!mDragging) { 354f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return false; 355f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 356f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mVelocityTracker.addMovement(ev); 357f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira final int action = ev.getAction(); 358f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira switch (action) { 359f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_OUTSIDE: 360f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_MOVE: 361f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (mCurrView != null) { 362f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float deltaX = ev.getX() - mInitialTouchPosX; 3634485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal // If the swipe started in the dead region, ignore it. 3644485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal if (mInitialTouchPosX <= (DEAD_REGION_FOR_SWIPE * mDensityScale)){ 3654485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal return true; 3664485ade4b8c949a222f8b98650a9a48d074dc87eVikram Aggarwal } 3676f4af489f6e10c7b576361bf69bcacabc2fb820cMindy Pereira // If the user has gone vertical and not gone horizontalish AT 368cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // LEAST minBeforeLock, switch to scroll. Otherwise, cancel 369cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // the swipe. 3706f0b2be9d3855e93ec2977b2736798c60adb9b7eMindy Pereira float minDistance = MIN_SWIPE; 371cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira if (Math.abs(deltaX) < minDistance) { 372cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // Don't start the drag until at least X distance has 373cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // occurred. 374cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira return true; 375cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira } 376cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // don't let items that can't be dismissed be dragged more 377cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // than maxScrollDistance 378f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { 379f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float size = getSize(mCurrAnimView); 380f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float maxScrollDistance = 0.15f * size; 381cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira if (Math.abs(deltaX) >= size) { 382cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira deltaX = deltaX > 0 ? maxScrollDistance : -maxScrollDistance; 383f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } else { 384cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira deltaX = maxScrollDistance 385cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira * (float) Math.sin((deltaX / size) * (Math.PI / 2)); 386f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 387f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 388a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira setTranslation(mCurrAnimView, deltaX); 389f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (FADE_OUT_DURING_SWIPE && mCanCurrViewBeDimissed) { 390a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira mCurrAnimView.setAlpha(getAlphaForOffset(mCurrAnimView)); 3917af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp if (mPrevView != null) { 3927af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp // Base how much the text of the prev item is faded 3937af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp // on how far the current item has moved. 3944d4531a63cff536d2ee1a2929d0820981df8516amindyp mPrevView.setTextAlpha(getTextAlphaForOffset(mCurrAnimView)); 3957af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 396f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 3972102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei invalidateGlobalRegion(mCurrView.getSwipeableView().getView()); 398f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 399f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira break; 400f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_UP: 401f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira case MotionEvent.ACTION_CANCEL: 402f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (mCurrView != null) { 403f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale; 404f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity); 405f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale; 406f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float velocity = getVelocity(mVelocityTracker); 407f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); 408f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 409f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira // Decide whether to dismiss the current view 410cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // Tweak constants below as required to prevent erroneous 411cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // swipe/dismiss 412f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira float translation = Math.abs(mCurrAnimView.getTranslationX()); 413cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira float currAnimViewSize = getSize(mCurrAnimView); 414cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // Long swipe = translation of .4 * width 415cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH 416cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira && translation > 0.4 * currAnimViewSize; 417cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // Fast swipe = > escapeVelocity and translation of .1 * 418cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira // width 419cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) 420cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira && (Math.abs(velocity) > Math.abs(perpendicularVelocity)) 421f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira && (velocity > 0) == (mCurrAnimView.getTranslationX() > 0) 422cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira && translation > 0.05 * currAnimViewSize; 423cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira if (LOG_SWIPE_DISMISS_VELOCITY) { 424b184bfe96fa3512af88260fce4f3cee3066fb28dScott Kennedy LogUtils.v(TAG, "Swipe/Dismiss: " + velocity + "/" + escapeVelocity + "/" 425cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira + perpendicularVelocity + ", x: " + translation + "/" 426cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira + currAnimViewSize); 427cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira } 428cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira 429cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) 430cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira && (childSwipedFastEnough || childSwipedFarEnough); 431f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 432f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira if (dismissChild) { 433a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f); 434f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } else { 435ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy snapChild(mCurrView); 436f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 437f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 438f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira break; 439f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 440f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira return true; 441f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 442f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 443f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira public interface Callback { 444f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira View getChildAtPosition(MotionEvent ev); 445f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 4463b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp void cancelDismissCounter(); 4473b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp 448d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp void onScroll(); 449d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp 4506c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira boolean canChildBeDismissed(SwipeableItemView v); 451f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 452f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira void onBeginDrag(View v); 453f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 4546c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira void onChildDismissed(SwipeableItemView v); 455f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira 4566c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira void onDragCancelled(SwipeableItemView v); 457866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 458ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao ConversationCheckedSet getCheckedSet(); 4597af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp 4607af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp LeaveBehindItem getLastSwipedItem(); 461f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira } 46207118a01f7183645957010779222b84930f75b4eMindy Pereira} 463