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 92362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang private float mChildSwipedFarEnoughFactor = 0.4f; 93362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang private float mChildSwipedFastEnoughFactor = 0.05f; 94362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang 9511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public SwipeHelper(Context context, int swipeDirection, SwipeHelperCallback callback, float densityScale, 9611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float pagingTouchSlop) { 9711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback = callback; 9811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mSwipeDirection = swipeDirection; 9911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker = VelocityTracker.obtain(); 10011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDensityScale = densityScale; 10111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mPagingTouchSlop = pagingTouchSlop; 10211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (SWIPE_ESCAPE_VELOCITY == -1) { 10311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Resources res = context.getResources(); 10411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee SWIPE_ESCAPE_VELOCITY = res.getInteger(R.integer.swipe_escape_velocity); 10511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee DEFAULT_ESCAPE_ANIMATION_DURATION = res.getInteger(R.integer.escape_animation_duration); 10611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MAX_ESCAPE_ANIMATION_DURATION = res.getInteger(R.integer.max_escape_animation_duration); 10711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MAX_DISMISS_VELOCITY = res.getInteger(R.integer.max_dismiss_velocity); 10811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee SNAP_ANIM_LEN = res.getInteger(R.integer.snap_animation_duration); 10911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee SWIPE_SCROLL_SLOP = res.getInteger(R.integer.swipe_scroll_slop); 11011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MIN_SWIPE = res.getDimension(R.dimen.min_swipe); 11111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MIN_VERT = res.getDimension(R.dimen.min_vert); 11211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee MIN_LOCK = res.getDimension(R.dimen.min_lock); 11311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 11411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 11511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 11611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void setDensityScale(float densityScale) { 11711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDensityScale = densityScale; 11811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 11911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 12011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void setPagingTouchSlop(float pagingTouchSlop) { 12111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mPagingTouchSlop = pagingTouchSlop; 12211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 12311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 124362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang public void setChildSwipedFarEnoughFactor(float factor) { 125362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang mChildSwipedFarEnoughFactor = factor; 126362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang } 127362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang 128362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang public void setChildSwipedFastEnoughFactor(float factor) { 129362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang mChildSwipedFastEnoughFactor = factor; 130362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang } 131362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang 13211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getVelocity(VelocityTracker vt) { 13311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mSwipeDirection == X ? vt.getXVelocity() : 13411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee vt.getYVelocity(); 13511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 13611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 13711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private ObjectAnimator createTranslationAnimation(View v, float newPos) { 13811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = ObjectAnimator.ofFloat(v, 13911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mSwipeDirection == X ? "translationX" : "translationY", newPos); 14011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return anim; 14111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 14211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 14311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private ObjectAnimator createDismissAnimation(View v, float newPos, int duration) { 14411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = createTranslationAnimation(v, newPos); 14511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.setInterpolator(sLinearInterpolator); 14611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.setDuration(duration); 14711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return anim; 14811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 14911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 15011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getPerpendicularVelocity(VelocityTracker vt) { 15111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mSwipeDirection == X ? vt.getYVelocity() : 15211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee vt.getXVelocity(); 15311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 15411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 15511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private void setTranslation(View v, float translate) { 15611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mSwipeDirection == X) { 15711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee v.setTranslationX(translate); 15811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 15911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee v.setTranslationY(translate); 16011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 16111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 16211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 16311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getSize(View v) { 16411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mSwipeDirection == X ? v.getMeasuredWidth() : 16511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee v.getMeasuredHeight(); 16611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 16711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 16811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void setMinAlpha(float minAlpha) { 16911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mMinAlpha = minAlpha; 17011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 17111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 17211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float getAlphaForOffset(View view) { 17311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float viewSize = getSize(view); 17411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final float fadeSize = ALPHA_FADE_END * viewSize; 17511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float result = mStartAlpha; 17611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float pos = view.getTranslationX(); 17711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (pos >= viewSize * ALPHA_FADE_START) { 17811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee result = mStartAlpha - (pos - viewSize * ALPHA_FADE_START) / fadeSize; 17911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else if (pos < viewSize * (mStartAlpha - ALPHA_FADE_START)) { 18011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee result = mStartAlpha + (viewSize * ALPHA_FADE_START + pos) / fadeSize; 18111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 18211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return Math.max(mMinAlpha, result); 18311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 18411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 18511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // invalidate the view's own bounds all the way up the view hierarchy 18611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static void invalidateGlobalRegion(View view) { 18711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion( 18811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view, 18911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom())); 19011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 19111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 19211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // invalidate a rectangle relative to the view's coordinate system all the way up the view 19311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // hierarchy 19411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static void invalidateGlobalRegion(View view, RectF childBounds) { 19511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // childBounds.offset(view.getTranslationX(), view.getTranslationY()); 19611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (DEBUG_INVALIDATE) 19711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Log.v(TAG, "-------------"); 19811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee while (view.getParent() != null && view.getParent() instanceof View) { 19911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view = (View) view.getParent(); 20011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view.getMatrix().mapRect(childBounds); 20111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view.invalidate((int) Math.floor(childBounds.left), 20211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) Math.floor(childBounds.top), 20311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) Math.ceil(childBounds.right), 20411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) Math.ceil(childBounds.bottom)); 20511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (DEBUG_INVALIDATE) { 20611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) 20711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + "," + (int) Math.floor(childBounds.top) 20811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + "," + (int) Math.ceil(childBounds.right) 20911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + "," + (int) Math.ceil(childBounds.bottom)); 21011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 21111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 21211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 21311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 21411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public boolean onInterceptTouchEvent(MotionEvent ev) { 21511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final int action = ev.getAction(); 21611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee switch (action) { 21711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_DOWN: 21811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = ev.getY(); 21911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDragging = false; 22011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrView = mCallback.getChildAtPosition(ev); 22111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.clear(); 22211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 22311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrAnimView = mCallback.getChildContentView(mCurrView); 22411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mStartAlpha = mCurrAnimView.getAlpha(); 22511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); 22611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.addMovement(ev); 22711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosX = ev.getX(); 22811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosY = ev.getY(); 22911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 23011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 23111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_MOVE: 23211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 23311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Check the movement direction. 23411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mLastY >= 0 && !mDragging) { 23511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float currY = ev.getY(); 23611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float currX = ev.getX(); 23711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaY = Math.abs(currY - mInitialTouchPosY); 23811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaX = Math.abs(currX - mInitialTouchPosX); 23911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (deltaY > SWIPE_SCROLL_SLOP && deltaY > (FACTOR * deltaX)) { 24011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = ev.getY(); 24111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onScroll(); 24211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return false; 24311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 24411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 24511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.addMovement(ev); 24611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float pos = ev.getX(); 24711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float delta = pos - mInitialTouchPosX; 24811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (Math.abs(delta) > mPagingTouchSlop) { 24911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onBeginDrag(mCallback.getChildContentView(mCurrView)); 25011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDragging = true; 25111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosX = ev.getX() - mCurrAnimView.getTranslationX(); 25211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mInitialTouchPosY = ev.getY(); 25311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 25411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 25511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = ev.getY(); 25611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 25711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_UP: 25811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_CANCEL: 25911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mDragging = false; 26011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrView = null; 26111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrAnimView = null; 26211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mLastY = -1; 26311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 26411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 26511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return mDragging; 26611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 26711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 26811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee /** 26911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * @param view The view to be dismissed 27011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * @param velocity The desired pixels/second speed at which the view should 27111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * move 27211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee */ 27311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private void dismissChild(final View view, float velocity) { 27411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final View animView = mCallback.getChildContentView(view); 27511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 27611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float newPos = determinePos(animView, velocity); 27711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee int duration = determineDuration(animView, newPos, velocity); 27811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 27911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 28011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = createDismissAnimation(animView, newPos, duration); 28111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addListener(new AnimatorListenerAdapter() { 28211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 28311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationEnd(Animator animation) { 2843686e68c873ffc83e086797abed6c883185737f2Yorke Lee mCallback.onChildDismissed(view); 28511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setLayerType(View.LAYER_TYPE_NONE, null); 28611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 28711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 28811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addUpdateListener(new AnimatorUpdateListener() { 28911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 29011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationUpdate(ValueAnimator animation) { 29111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { 29211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setAlpha(getAlphaForOffset(animView)); 29311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 29411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion(animView); 29511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 29611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 29711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.start(); 29811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 29911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 30011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private int determineDuration(View animView, float newPos, float velocity) { 30111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee int duration = MAX_ESCAPE_ANIMATION_DURATION; 30211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (velocity != 0) { 30311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee duration = Math 30411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee .min(duration, 30511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee (int) (Math.abs(newPos - animView.getTranslationX()) * 1000f / Math 30611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee .abs(velocity))); 30711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 30811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee duration = DEFAULT_ESCAPE_ANIMATION_DURATION; 30911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 31011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return duration; 31111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 31211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 31311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee private float determinePos(View animView, float velocity) { 31411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float newPos = 0; 31511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (velocity < 0 || (velocity == 0 && animView.getTranslationX() < 0) 31611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // if we use the Menu to dismiss an item in landscape, animate up 31711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee || (velocity == 0 && animView.getTranslationX() == 0 && mSwipeDirection == Y)) { 31811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee newPos = -getSize(animView); 31911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 32011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee newPos = getSize(animView); 32111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 32211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return newPos; 32311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 32411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 32511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void snapChild(final View view, float velocity) { 32611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final View animView = mCallback.getChildContentView(view); 32711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); 32811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee ObjectAnimator anim = createTranslationAnimation(animView, 0); 32911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee int duration = SNAP_ANIM_LEN; 33011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.setDuration(duration); 33111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.addUpdateListener(new AnimatorUpdateListener() { 33211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 33311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationUpdate(ValueAnimator animation) { 33411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { 33511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setAlpha(getAlphaForOffset(animView)); 33611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 33711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion(animView); 33811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 33911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 3405b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang anim.addListener(new AnimatorListenerAdapter() { 34111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 34211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onAnimationEnd(Animator animation) { 34311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee animView.setAlpha(mStartAlpha); 34411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onDragCancelled(mCurrView); 34511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 34611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee }); 34711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee anim.start(); 34811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 34911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 35011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public boolean onTouchEvent(MotionEvent ev) { 35111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (!mDragging || mProtected) { 35211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return false; 35311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 35411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.addMovement(ev); 35511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee final int action = ev.getAction(); 35611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee switch (action) { 35711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_OUTSIDE: 35811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_MOVE: 35911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 36011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaX = ev.getX() - mInitialTouchPosX; 36111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float deltaY = Math.abs(ev.getY() - mInitialTouchPosY); 36211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // If the user has gone vertical and not gone horizontalish AT 36311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // LEAST minBeforeLock, switch to scroll. Otherwise, cancel 36411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // the swipe. 36511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (!mDragging && deltaY > MIN_VERT && (Math.abs(deltaX)) < MIN_LOCK 36611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && deltaY > (FACTOR * Math.abs(deltaX))) { 36711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCallback.onScroll(); 36811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return false; 36911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 37011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float minDistance = MIN_SWIPE; 37111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (Math.abs(deltaX) < minDistance) { 37211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Don't start the drag until at least X distance has 37311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // occurred. 37411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return true; 37511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 37611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // don't let items that can't be dismissed be dragged more 37711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // than maxScrollDistance 37811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { 37911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float size = getSize(mCurrAnimView); 38011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float maxScrollDistance = 0.15f * size; 38111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (Math.abs(deltaX) >= size) { 38211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee deltaX = deltaX > 0 ? maxScrollDistance : -maxScrollDistance; 38311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 38411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee deltaX = maxScrollDistance 38511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee * (float) Math.sin((deltaX / size) * (Math.PI / 2)); 38611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 38711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 38811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee setTranslation(mCurrAnimView, deltaX); 38911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (FADE_OUT_DURING_SWIPE && mCanCurrViewBeDimissed) { 39011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mCurrAnimView.setAlpha(getAlphaForOffset(mCurrAnimView)); 39111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 39211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee invalidateGlobalRegion(mCallback.getChildContentView(mCurrView)); 39311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 39411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 39511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_UP: 39611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee case MotionEvent.ACTION_CANCEL: 39711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (mCurrView != null) { 39811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale; 39911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity); 40011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale; 40111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float velocity = getVelocity(mVelocityTracker); 40211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); 40311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 40411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Decide whether to dismiss the current view 40511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // Tweak constants below as required to prevent erroneous 40611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee // swipe/dismiss 40711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float translation = Math.abs(mCurrAnimView.getTranslationX()); 40811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee float currAnimViewSize = getSize(mCurrAnimView); 409362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang // Long swipe = translation of {@link #mChildSwipedFarEnoughFactor} * width 41011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH 411362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang && translation > mChildSwipedFarEnoughFactor * currAnimViewSize; 412362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang // Fast swipe = > escapeVelocity and translation of 413362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang // {@link #mChildSwipedFastEnoughFactor} * width 41411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) 41511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && (Math.abs(velocity) > Math.abs(perpendicularVelocity)) 41611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && (velocity > 0) == (mCurrAnimView.getTranslationX() > 0) 417362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang && translation > mChildSwipedFastEnoughFactor * currAnimViewSize; 41811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (LOG_SWIPE_DISMISS_VELOCITY) { 41911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee Log.v(TAG, "Swipe/Dismiss: " + velocity + "/" + escapeVelocity + "/" 42011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + perpendicularVelocity + ", x: " + translation + "/" 42111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee + currAnimViewSize); 42211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 42311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 42411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) 42511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee && (childSwipedFastEnough || childSwipedFarEnough); 42611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 42711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee if (dismissChild) { 42811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f); 42911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } else { 43011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee snapChild(mCurrView, velocity); 43111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee break; 43411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return true; 43611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 43711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 43811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static void setSwipeable(View view, boolean swipeable) { 43911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee view.setTag(IS_SWIPEABLE_TAG, swipeable ? IS_SWIPEABLE : null); 44011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 44111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 44211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public static boolean isSwipeable(View view) { 44311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee return IS_SWIPEABLE == view.getTag(IS_SWIPEABLE_TAG); 44411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 44511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 44611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public interface SwipeHelperCallback { 44711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee View getChildAtPosition(MotionEvent ev); 44811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 44911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee View getChildContentView(View v); 45011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onScroll(); 45211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee boolean canChildBeDismissed(View v); 45411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onBeginDrag(View v); 45611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45711ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onChildDismissed(View v); 45811ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 45911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee void onDragCancelled(View v); 46011ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 46211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46311ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public interface OnItemGestureListener { 46411ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onSwipe(View view); 46511ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 46611ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee public void onTouch(); 4675a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee 4685a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee public boolean isSwipeEnabled(); 46911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee } 470362c4441b65f63dfc3cf933d569aba6e00dc168aHongwei Wang} 471