SwipeHelper.java revision 5a1db1cd6a8addc0401529454bde6e1d15f215a0
111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee/* 211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * Copyright (C) 2012 Google Inc. 311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * Licensed to The Android Open Source Project. 411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * 511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * Licensed under the Apache License, Version 2.0 (the "License"); 611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * you may not use this file except in compliance with the License. 711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * You may obtain a copy of the License at 811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * 911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * http://www.apache.org/licenses/LICENSE-2.0 1011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * 1111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * Unless required by applicable law or agreed to in writing, software 1211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * distributed under the License is distributed on an "AS IS" BASIS, 1311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * See the License for the specific language governing permissions and 1511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * limitations under the License. 1611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee */ 1711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 1811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leepackage com.android.dialer.list; 1911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 2011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.animation.Animator; 2111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.animation.AnimatorListenerAdapter; 2211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.animation.ObjectAnimator; 2311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.animation.ValueAnimator; 2411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.animation.ValueAnimator.AnimatorUpdateListener; 2511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.content.Context; 2611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.content.res.Resources; 2711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.graphics.RectF; 2811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.util.Log; 2911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.view.MotionEvent; 3011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.view.VelocityTracker; 3111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.view.View; 3211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport android.view.animation.LinearInterpolator; 3311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 3411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leeimport com.android.dialer.R; 3511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 3611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee/** 3711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * Copy of packages/apps/UnifiedEmail - com.android.mail.ui.SwipeHelper with changes. 3811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee */ 3911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leepublic class SwipeHelper { 4011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee static final String TAG = SwipeHelper.class.getSimpleName(); 4111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final boolean DEBUG_INVALIDATE = false; 4211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final boolean CONSTRAIN_SWIPE = true; 4311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final boolean FADE_OUT_DURING_SWIPE = true; 4411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; 4511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final boolean LOG_SWIPE_DISMISS_VELOCITY = false; // STOPSHIP - DEBUG ONLY 4611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 4711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static final int IS_SWIPEABLE_TAG = R.id.is_swipeable_tag; 4811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static final Object IS_SWIPEABLE = new Object(); 4911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 5011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static final int X = 0; 5111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static final int Y = 1; 5211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 5311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static LinearInterpolator sLinearInterpolator = new LinearInterpolator(); 5411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 5511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static int SWIPE_ESCAPE_VELOCITY = -1; 5611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static int DEFAULT_ESCAPE_ANIMATION_DURATION; 5711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static int MAX_ESCAPE_ANIMATION_DURATION; 5811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static int MAX_DISMISS_VELOCITY; 5911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static int SNAP_ANIM_LEN; 6011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static int SWIPE_SCROLL_SLOP; 6111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static float MIN_SWIPE; 6211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static float MIN_VERT; 6311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static float MIN_LOCK; 6411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 6511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static float ALPHA_FADE_START = 0f; // fraction of thumbnail width 6611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // where fade starts 6711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee static final float ALPHA_FADE_END = 0.7f; // fraction of thumbnail width 6811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // beyond which alpha->0 6911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final float FACTOR = 1.2f; 7011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 7111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private static final int PROTECTION_PADDING = 50; 7211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 7311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mMinAlpha = 0.3f; 7411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 7511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mPagingTouchSlop; 7611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private final SwipeHelperCallback mCallback; 7711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private final int mSwipeDirection; 7811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private final VelocityTracker mVelocityTracker; 7911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 8011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mInitialTouchPosX; 8111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private boolean mDragging; 8211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private View mCurrView; 8311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private View mCurrAnimView; 8411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private boolean mCanCurrViewBeDimissed; 8511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mDensityScale; 8611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mLastY; 8711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mInitialTouchPosY; 8811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 8911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float mStartAlpha; 9011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private boolean mProtected = false; 9111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 9211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public SwipeHelper(Context context, int swipeDirection, SwipeHelperCallback callback, float densityScale, 9311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float pagingTouchSlop) { 9411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback = callback; 9511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mSwipeDirection = swipeDirection; 9611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker = VelocityTracker.obtain(); 9711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDensityScale = densityScale; 9811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mPagingTouchSlop = pagingTouchSlop; 9911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (SWIPE_ESCAPE_VELOCITY == -1) { 10011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Resources res = context.getResources(); 10111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee SWIPE_ESCAPE_VELOCITY = res.getInteger(R.integer.swipe_escape_velocity); 10211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee DEFAULT_ESCAPE_ANIMATION_DURATION = res.getInteger(R.integer.escape_animation_duration); 10311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MAX_ESCAPE_ANIMATION_DURATION = res.getInteger(R.integer.max_escape_animation_duration); 10411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MAX_DISMISS_VELOCITY = res.getInteger(R.integer.max_dismiss_velocity); 10511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee SNAP_ANIM_LEN = res.getInteger(R.integer.snap_animation_duration); 10611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee SWIPE_SCROLL_SLOP = res.getInteger(R.integer.swipe_scroll_slop); 10711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MIN_SWIPE = res.getDimension(R.dimen.min_swipe); 10811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MIN_VERT = res.getDimension(R.dimen.min_vert); 10911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MIN_LOCK = res.getDimension(R.dimen.min_lock); 11011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 11111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 11211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 11311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void setDensityScale(float densityScale) { 11411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDensityScale = densityScale; 11511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 11611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 11711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void setPagingTouchSlop(float pagingTouchSlop) { 11811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mPagingTouchSlop = pagingTouchSlop; 11911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 12011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 12111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getVelocity(VelocityTracker vt) { 12211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mSwipeDirection == X ? vt.getXVelocity() : 12311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee vt.getYVelocity(); 12411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 12511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 12611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private ObjectAnimator createTranslationAnimation(View v, float newPos) { 12711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = ObjectAnimator.ofFloat(v, 12811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mSwipeDirection == X ? "translationX" : "translationY", newPos); 12911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return anim; 13011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 13111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 13211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private ObjectAnimator createDismissAnimation(View v, float newPos, int duration) { 13311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = createTranslationAnimation(v, newPos); 13411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.setInterpolator(sLinearInterpolator); 13511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.setDuration(duration); 13611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return anim; 13711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 13811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 13911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getPerpendicularVelocity(VelocityTracker vt) { 14011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mSwipeDirection == X ? vt.getYVelocity() : 14111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee vt.getXVelocity(); 14211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 14311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 14411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private void setTranslation(View v, float translate) { 14511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mSwipeDirection == X) { 14611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee v.setTranslationX(translate); 14711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 14811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee v.setTranslationY(translate); 14911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 15011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 15111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 15211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getSize(View v) { 15311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mSwipeDirection == X ? v.getMeasuredWidth() : 15411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee v.getMeasuredHeight(); 15511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 15611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 15711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void setMinAlpha(float minAlpha) { 15811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mMinAlpha = minAlpha; 15911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 16011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 16111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getAlphaForOffset(View view) { 16211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float viewSize = getSize(view); 16311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final float fadeSize = ALPHA_FADE_END * viewSize; 16411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float result = mStartAlpha; 16511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float pos = view.getTranslationX(); 16611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (pos >= viewSize * ALPHA_FADE_START) { 16711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee result = mStartAlpha - (pos - viewSize * ALPHA_FADE_START) / fadeSize; 16811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else if (pos < viewSize * (mStartAlpha - ALPHA_FADE_START)) { 16911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee result = mStartAlpha + (viewSize * ALPHA_FADE_START + pos) / fadeSize; 17011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 17111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return Math.max(mMinAlpha, result); 17211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 17311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 17411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // invalidate the view's own bounds all the way up the view hierarchy 17511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static void invalidateGlobalRegion(View view) { 17611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion( 17711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view, 17811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom())); 17911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 18011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 18111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // invalidate a rectangle relative to the view's coordinate system all the way up the view 18211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // hierarchy 18311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static void invalidateGlobalRegion(View view, RectF childBounds) { 18411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // childBounds.offset(view.getTranslationX(), view.getTranslationY()); 18511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (DEBUG_INVALIDATE) 18611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Log.v(TAG, "-------------"); 18711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee while (view.getParent() != null && view.getParent() instanceof View) { 18811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view = (View) view.getParent(); 18911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view.getMatrix().mapRect(childBounds); 19011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view.invalidate((int) Math.floor(childBounds.left), 19111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) Math.floor(childBounds.top), 19211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) Math.ceil(childBounds.right), 19311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) Math.ceil(childBounds.bottom)); 19411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (DEBUG_INVALIDATE) { 19511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) 19611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + "," + (int) Math.floor(childBounds.top) 19711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + "," + (int) Math.ceil(childBounds.right) 19811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + "," + (int) Math.ceil(childBounds.bottom)); 19911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 20011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 20111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 20211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 20311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public boolean onInterceptTouchEvent(MotionEvent ev) { 20411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final int action = ev.getAction(); 20511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee switch (action) { 20611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_DOWN: 20711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = ev.getY(); 20811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDragging = false; 20911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrView = mCallback.getChildAtPosition(ev); 21011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.clear(); 21111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 21211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrAnimView = mCallback.getChildContentView(mCurrView); 21311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mStartAlpha = mCurrAnimView.getAlpha(); 21411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); 21511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.addMovement(ev); 21611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosX = ev.getX(); 21711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosY = ev.getY(); 21811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 21911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 22011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_MOVE: 22111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 22211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Check the movement direction. 22311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mLastY >= 0 && !mDragging) { 22411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float currY = ev.getY(); 22511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float currX = ev.getX(); 22611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaY = Math.abs(currY - mInitialTouchPosY); 22711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaX = Math.abs(currX - mInitialTouchPosX); 22811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (deltaY > SWIPE_SCROLL_SLOP && deltaY > (FACTOR * deltaX)) { 22911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = ev.getY(); 23011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onScroll(); 23111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return false; 23211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 23311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 23411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.addMovement(ev); 23511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float pos = ev.getX(); 23611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float delta = pos - mInitialTouchPosX; 23711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (Math.abs(delta) > mPagingTouchSlop) { 23811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onBeginDrag(mCallback.getChildContentView(mCurrView)); 23911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDragging = true; 24011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosX = ev.getX() - mCurrAnimView.getTranslationX(); 24111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosY = ev.getY(); 24211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 24311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 24411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = ev.getY(); 24511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 24611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_UP: 24711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_CANCEL: 24811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDragging = false; 24911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrView = null; 25011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrAnimView = null; 25111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = -1; 25211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 25311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 25411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mDragging; 25511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 25611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 25711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee /** 25811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * @param view The view to be dismissed 25911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * @param velocity The desired pixels/second speed at which the view should 26011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * move 26111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee */ 26211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private void dismissChild(final View view, float velocity) { 26311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final View animView = mCallback.getChildContentView(view); 26411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 26511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float newPos = determinePos(animView, velocity); 26611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee int duration = determineDuration(animView, newPos, velocity); 26711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 26811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 26911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = createDismissAnimation(animView, newPos, duration); 27011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addListener(new AnimatorListenerAdapter() { 27111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 27211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationEnd(Animator animation) { 27311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onChildDismissed(mCurrView); 27411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setLayerType(View.LAYER_TYPE_NONE, null); 27511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 27611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 27711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addUpdateListener(new AnimatorUpdateListener() { 27811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 27911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationUpdate(ValueAnimator animation) { 28011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { 28111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setAlpha(getAlphaForOffset(animView)); 28211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 28311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion(animView); 28411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 28511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 28611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.start(); 28711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 28811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 28911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private int determineDuration(View animView, float newPos, float velocity) { 29011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee int duration = MAX_ESCAPE_ANIMATION_DURATION; 29111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (velocity != 0) { 29211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee duration = Math 29311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee .min(duration, 29411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) (Math.abs(newPos - animView.getTranslationX()) * 1000f / Math 29511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee .abs(velocity))); 29611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 29711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee duration = DEFAULT_ESCAPE_ANIMATION_DURATION; 29811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 29911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return duration; 30011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 30111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 30211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float determinePos(View animView, float velocity) { 30311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float newPos = 0; 30411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (velocity < 0 || (velocity == 0 && animView.getTranslationX() < 0) 30511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // if we use the Menu to dismiss an item in landscape, animate up 30611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee || (velocity == 0 && animView.getTranslationX() == 0 && mSwipeDirection == Y)) { 30711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee newPos = -getSize(animView); 30811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 30911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee newPos = getSize(animView); 31011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 31111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return newPos; 31211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 31311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 31411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void snapChild(final View view, float velocity) { 31511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final View animView = mCallback.getChildContentView(view); 31611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 31711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = createTranslationAnimation(animView, 0); 31811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee int duration = SNAP_ANIM_LEN; 31911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.setDuration(duration); 32011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addUpdateListener(new AnimatorUpdateListener() { 32111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 32211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationUpdate(ValueAnimator animation) { 32311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { 32411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setAlpha(getAlphaForOffset(animView)); 32511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 32611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion(animView); 32711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 32811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 32911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addListener(new Animator.AnimatorListener() { 33011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 33111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationStart(Animator animation) { 33211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 33311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 33411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 33511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationEnd(Animator animation) { 33611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setAlpha(mStartAlpha); 33711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onDragCancelled(mCurrView); 33811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 33911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 34011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 34111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationCancel(Animator animation) { 34211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 34311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 34411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 34511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationRepeat(Animator animation) { 34611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 34711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 34811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.start(); 34911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 35011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 35111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public boolean onTouchEvent(MotionEvent ev) { 35211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (!mDragging || mProtected) { 35311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return false; 35411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 35511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.addMovement(ev); 35611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final int action = ev.getAction(); 35711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee switch (action) { 35811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_OUTSIDE: 35911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_MOVE: 36011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 36111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaX = ev.getX() - mInitialTouchPosX; 36211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaY = Math.abs(ev.getY() - mInitialTouchPosY); 36311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // If the user has gone vertical and not gone horizontalish AT 36411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // LEAST minBeforeLock, switch to scroll. Otherwise, cancel 36511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // the swipe. 36611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (!mDragging && deltaY > MIN_VERT && (Math.abs(deltaX)) < MIN_LOCK 36711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && deltaY > (FACTOR * Math.abs(deltaX))) { 36811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onScroll(); 36911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return false; 37011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 37111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float minDistance = MIN_SWIPE; 37211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (Math.abs(deltaX) < minDistance) { 37311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Don't start the drag until at least X distance has 37411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // occurred. 37511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return true; 37611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 37711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // don't let items that can't be dismissed be dragged more 37811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // than maxScrollDistance 37911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { 38011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float size = getSize(mCurrAnimView); 38111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float maxScrollDistance = 0.15f * size; 38211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (Math.abs(deltaX) >= size) { 38311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee deltaX = deltaX > 0 ? maxScrollDistance : -maxScrollDistance; 38411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 38511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee deltaX = maxScrollDistance 38611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * (float) Math.sin((deltaX / size) * (Math.PI / 2)); 38711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 38811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 38911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee setTranslation(mCurrAnimView, deltaX); 39011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (FADE_OUT_DURING_SWIPE && mCanCurrViewBeDimissed) { 39111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrAnimView.setAlpha(getAlphaForOffset(mCurrAnimView)); 39211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 39311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion(mCallback.getChildContentView(mCurrView)); 39411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 39511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 39611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_UP: 39711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_CANCEL: 39811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 39911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale; 40011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity); 40111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale; 40211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float velocity = getVelocity(mVelocityTracker); 40311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); 40411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 40511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Decide whether to dismiss the current view 40611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Tweak constants below as required to prevent erroneous 40711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // swipe/dismiss 40811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float translation = Math.abs(mCurrAnimView.getTranslationX()); 40911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float currAnimViewSize = getSize(mCurrAnimView); 41011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Long swipe = translation of .4 * width 41111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH 41211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && translation > 0.4 * currAnimViewSize; 41311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Fast swipe = > escapeVelocity and translation of .1 * 41411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // width 41511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) 41611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && (Math.abs(velocity) > Math.abs(perpendicularVelocity)) 41711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && (velocity > 0) == (mCurrAnimView.getTranslationX() > 0) 41811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && translation > 0.05 * currAnimViewSize; 41911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (LOG_SWIPE_DISMISS_VELOCITY) { 42011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Log.v(TAG, "Swipe/Dismiss: " + velocity + "/" + escapeVelocity + "/" 42111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + perpendicularVelocity + ", x: " + translation + "/" 42211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + currAnimViewSize); 42311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 42411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 42511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) 42611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && (childSwipedFastEnough || childSwipedFarEnough); 42711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 42811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (dismissChild) { 42911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f); 43011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 43111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee snapChild(mCurrView, velocity); 43211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 43511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return true; 43711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 43911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static void setSwipeable(View view, boolean swipeable) { 44011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view.setTag(IS_SWIPEABLE_TAG, swipeable ? IS_SWIPEABLE : null); 44111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 44211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 44311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static boolean isSwipeable(View view) { 44411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return IS_SWIPEABLE == view.getTag(IS_SWIPEABLE_TAG); 44511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 44611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 44711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public interface SwipeHelperCallback { 44811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee View getChildAtPosition(MotionEvent ev); 44911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee View getChildContentView(View v); 45111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onScroll(); 45311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean canChildBeDismissed(View v); 45511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onBeginDrag(View v); 45711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onChildDismissed(View v); 45911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onDragCancelled(View v); 46111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 46311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public interface OnItemGestureListener { 46511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onSwipe(View view); 46611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onTouch(); 4685a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee 4695a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee public boolean isSwipeEnabled(); 47011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 47111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee}