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) {
2672102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei        final View animView = mCurrView.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) {
2776c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                mCallback.onChildDismissed(mCurrView);
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
458866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        ConversationSelectionSet getSelectionSet();
4597af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp
4607af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp        LeaveBehindItem getLastSwipedItem();
461f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
46207118a01f7183645957010779222b84930f75b4eMindy Pereira}
463