/** * @param view The view to be dismissed * @param velocity The desired pixels/second speed at which the view should move */ private void dismissChild(final SwipeableItemView view, float velocity) { final View animView = mCurrView.getSwipeableView().getView(); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); float newPos = determinePos(animView, velocity); int duration = determineDuration(animView, newPos, velocity); Utils.enableHardwareLayer(animView); ObjectAnimator anim = createDismissAnimation(animView, newPos, duration); anim.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mCallback.onChildDismissed(mCurrView); animView.setLayerType(View.LAYER_TYPE_NONE, null); } }); anim.addUpdateListener( new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { animView.setAlpha(getAlphaForOffset(animView)); } invalidateGlobalRegion(animView); } }); anim.start(); }
public void snapChild(final SwipeableItemView view) { final View animView = view.getSwipeableView().getView(); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); final ObjectAnimator anim = createTranslationAnimation(animView, 0); final int duration = SNAP_ANIM_LEN; anim.setDuration(duration); anim.addUpdateListener( new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { animView.setAlpha(getAlphaForOffset(animView)); } invalidateGlobalRegion(animView); } }); anim.addListener( new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { animView.setAlpha(1.0f); mCallback.onDragCancelled(mCurrView); } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }); anim.start(); }
public boolean onTouchEvent(MotionEvent ev) { if (!mDragging) { return false; } mVelocityTracker.addMovement(ev); final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_MOVE: if (mCurrView != null) { float deltaX = ev.getX() - mInitialTouchPosX; // If the swipe started in the dead region, ignore it. if (mInitialTouchPosX <= (DEAD_REGION_FOR_SWIPE * mDensityScale)) { return true; } // If the user has gone vertical and not gone horizontalish AT // LEAST minBeforeLock, switch to scroll. Otherwise, cancel // the swipe. float minDistance = MIN_SWIPE; if (Math.abs(deltaX) < minDistance) { // Don't start the drag until at least X distance has // occurred. return true; } // don't let items that can't be dismissed be dragged more // than maxScrollDistance if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { float size = getSize(mCurrAnimView); float maxScrollDistance = 0.15f * size; if (Math.abs(deltaX) >= size) { deltaX = deltaX > 0 ? maxScrollDistance : -maxScrollDistance; } else { deltaX = maxScrollDistance * (float) Math.sin((deltaX / size) * (Math.PI / 2)); } } setTranslation(mCurrAnimView, deltaX); if (FADE_OUT_DURING_SWIPE && mCanCurrViewBeDimissed) { mCurrAnimView.setAlpha(getAlphaForOffset(mCurrAnimView)); if (mPrevView != null) { // Base how much the text of the prev item is faded // on how far the current item has moved. mPrevView.setTextAlpha(getTextAlphaForOffset(mCurrAnimView)); } } invalidateGlobalRegion(mCurrView.getSwipeableView().getView()); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (mCurrView != null) { float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale; mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity); float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale; float velocity = getVelocity(mVelocityTracker); float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker); // Decide whether to dismiss the current view // Tweak constants below as required to prevent erroneous // swipe/dismiss float translation = Math.abs(mCurrAnimView.getTranslationX()); float currAnimViewSize = getSize(mCurrAnimView); // Long swipe = translation of .4 * width boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH && translation > 0.4 * currAnimViewSize; // Fast swipe = > escapeVelocity and translation of .1 * // width boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) && (Math.abs(velocity) > Math.abs(perpendicularVelocity)) && (velocity > 0) == (mCurrAnimView.getTranslationX() > 0) && translation > 0.05 * currAnimViewSize; if (LOG_SWIPE_DISMISS_VELOCITY) { LogUtils.v( TAG, "Swipe/Dismiss: " + velocity + "/" + escapeVelocity + "/" + perpendicularVelocity + ", x: " + translation + "/" + currAnimViewSize); } boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) && (childSwipedFastEnough || childSwipedFarEnough); if (dismissChild) { dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f); } else { snapChild(mCurrView); } } break; } return true; }
public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: mLastY = ev.getY(); mDragging = false; View view = mCallback.getChildAtPosition(ev); if (view instanceof SwipeableItemView) { mCurrView = (SwipeableItemView) view; } else { // If the touched item is not a swipeable one, clean the cache in // mCurrView to make sure nothing will be swiped for this action mCurrView = null; } mVelocityTracker.clear(); if (mCurrView != null) { mCurrAnimView = mCurrView.getSwipeableView().getView(); mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); mVelocityTracker.addMovement(ev); mInitialTouchPosX = ev.getX(); mInitialTouchPosY = ev.getY(); } mCallback.cancelDismissCounter(); break; case MotionEvent.ACTION_MOVE: if (mCurrView != null) { // Check the movement direction. if (mLastY >= 0 && !mDragging) { float currY = ev.getY(); float currX = ev.getX(); float deltaY = Math.abs(currY - mInitialTouchPosY); float deltaX = Math.abs(currX - mInitialTouchPosX); if (deltaY > mCurrView.getMinAllowScrollDistance() && deltaY > (FACTOR * deltaX)) { mLastY = ev.getY(); mCallback.onScroll(); return false; } } mVelocityTracker.addMovement(ev); float pos = ev.getX(); float delta = pos - mInitialTouchPosX; if (Math.abs(delta) > mPagingTouchSlop) { mCallback.onBeginDrag(mCurrView.getSwipeableView().getView()); mPrevView = mCallback.getLastSwipedItem(); mDragging = true; mInitialTouchPosX = ev.getX() - mCurrAnimView.getTranslationX(); mInitialTouchPosY = ev.getY(); } } mLastY = ev.getY(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mDragging = false; mCurrView = null; mCurrAnimView = null; mLastY = -1; break; } return mDragging; }