public static boolean isChildInCenterY(RecyclerView recyclerView, View view) { int childCount = recyclerView.getChildCount(); int[] rvLocationOnScreen = new int[2]; int[] vLocationOnScreen = new int[2]; recyclerView.getLocationOnScreen(rvLocationOnScreen); int middleY = (int) (rvLocationOnScreen[1] + recyclerView.getHeight() * recyclerView.getScaleY() / 2); if (childCount > 0) { view.getLocationOnScreen(vLocationOnScreen); if (vLocationOnScreen[1] <= middleY && vLocationOnScreen[1] + view.getHeight() * view.getScaleY() >= middleY) { return true; } } return false; }
public static boolean isChildInCenterX(RecyclerView recyclerView, View view) { int childCount = recyclerView.getChildCount(); int[] lvLocationOnScreen = new int[2]; int[] vLocationOnScreen = new int[2]; recyclerView.getLocationOnScreen(lvLocationOnScreen); int middleX = (int) (lvLocationOnScreen[0] + recyclerView.getWidth() * recyclerView.getScaleX() / 2); if (childCount > 0) { view.getLocationOnScreen(vLocationOnScreen); if (vLocationOnScreen[0] <= middleX && vLocationOnScreen[0] + view.getWidth() * view.getScaleX() >= middleX) { return true; } } return false; }
/** 滑动开始准备 */ private void actionDown(MotionEvent motionEvent) { if (mPaused) { return; } // 找到被点击的 view 和位置(包括 top left right bottom) Rect rect = new Rect(); int childCount = mRecyclerView.getChildCount(); // location 指的是 RecyclerView 左上角以整个屏幕的左上角为参照物的坐标 int[] location = new int[2]; mRecyclerView.getLocationOnScreen(location); // 此处的 x y 指的是触摸点以 location 为参照物时的坐标 int x = (int) motionEvent.getRawX() - location[0]; int y = (int) motionEvent.getRawY() - location[1]; View child; for (int i = 0; i < childCount; i++) { child = mRecyclerView.getChildAt(i); child.getHitRect(rect); if (rect.contains(x, y)) { mDownView = child; break; } } // 找到相应的 view 并且该 view 不处于执行动画状态 if (mDownView != null && mAnimatingPosition != mRecyclerView.getChildAdapterPosition(mDownView)) { mAlpha = mDownView.getAlpha(); mDownX = motionEvent.getRawX(); mDownY = motionEvent.getRawY(); mDownPosition = mRecyclerView.getChildAdapterPosition(mDownView); if (mSwipeListener.canSwipe(mDownPosition)) { // ?添加速度追踪器 mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(motionEvent); } else { mDownView = null; } } }
private boolean handleTouchEvent(MotionEvent motionEvent) { if (mViewWidth < 2) { mViewWidth = mRecyclerView.getWidth(); } switch (motionEvent.getActionMasked()) { case MotionEvent.ACTION_DOWN: { if (mPaused) { break; } // Find the child view that was touched (perform a hit test) Rect rect = new Rect(); int childCount = mRecyclerView.getChildCount(); int[] listViewCoords = new int[2]; mRecyclerView.getLocationOnScreen(listViewCoords); int x = (int) motionEvent.getRawX() - listViewCoords[0]; int y = (int) motionEvent.getRawY() - listViewCoords[1]; View child; for (int i = 0; i < childCount; i++) { child = mRecyclerView.getChildAt(i); child.getHitRect(rect); if (rect.contains(x, y)) { mDownView = child; break; } } if (mDownView != null) { mDownX = motionEvent.getRawX(); mDownY = motionEvent.getRawY(); mDownPosition = mRecyclerView.getChildAdapterPosition(mDownView); mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(motionEvent); mFgView = mDownView.findViewById(mFgID); } break; } case MotionEvent.ACTION_CANCEL: { if (mVelocityTracker == null) { break; } if (mDownView != null && mSwiping) { // cancel mFgView.animate().translationX(0).setDuration(ANIMATION_FAST).setListener(null); } mVelocityTracker.recycle(); mVelocityTracker = null; mDownX = 0; mDownY = 0; mDownView = null; mDownPosition = ListView.INVALID_POSITION; mSwiping = false; mBgView = null; break; } case MotionEvent.ACTION_UP: { if (mVelocityTracker == null) { break; } mFinalDelta = motionEvent.getRawX() - mDownX; mVelocityTracker.addMovement(motionEvent); mVelocityTracker.computeCurrentVelocity(1000); float velocityX = mVelocityTracker.getXVelocity(); float absVelocityX = Math.abs(velocityX); float absVelocityY = Math.abs(mVelocityTracker.getYVelocity()); boolean dismiss = false; boolean dismissRight = false; if (Math.abs(mFinalDelta) > mViewWidth / 2 && mSwiping) { dismiss = true; dismissRight = mFinalDelta > 0; } else if (mMinFlingVelocity <= absVelocityX && absVelocityX <= mMaxFlingVelocity && absVelocityY < absVelocityX && mSwiping) { // dismiss only if flinging in the same direction as dragging dismiss = (velocityX < 0) == (mFinalDelta < 0); dismissRight = mVelocityTracker.getXVelocity() > 0; } if (dismiss && mDownPosition != ListView.INVALID_POSITION && mSwipeListener.canSwipe(mDownPosition)) { // dismiss ++mDismissAnimationRefCount; mBgView.animate().alpha(1).setDuration(ANIMATION_FAST); mFgView .animate() .translationX(dismissRight ? mViewWidth : -mViewWidth) .setDuration(ANIMATION_FAST) .setListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mFgView.animate().translationX(0); // Esto hace que regrese a su posision :) } }); } else { // cancel mFgView.animate().translationX(0).setDuration(ANIMATION_FAST).setListener(null); } mVelocityTracker.recycle(); mVelocityTracker = null; mDownX = 0; mDownY = 0; mDownView = null; mDownPosition = ListView.INVALID_POSITION; mSwiping = false; mBgView = null; break; } case MotionEvent.ACTION_MOVE: { if (mVelocityTracker == null || mPaused) { break; } mVelocityTracker.addMovement(motionEvent); float deltaX = motionEvent.getRawX() - mDownX; float deltaY = motionEvent.getRawY() - mDownY; if (!mSwiping && Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) { mSwiping = true; mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop); } if (mSwiping) { if (mBgView == null) { mBgView = mDownView.findViewById(mBgID); mBgView.setVisibility(View.VISIBLE); listener.holaView((deltaX - mSwipingSlop) > 0, mBgView); } mFgView.setTranslationX(deltaX - mSwipingSlop); return true; } break; } } return false; }
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) private boolean handleTouchEvent(MotionEvent motionEvent) { if (mViewWidth < 2) { mViewWidth = mRecyclerView.getWidth(); } switch (motionEvent.getActionMasked()) { case MotionEvent.ACTION_DOWN: { if (mPaused) { break; } // Find the child view that was touched (perform a hit test) Rect rect = new Rect(); int childCount = mRecyclerView.getChildCount(); int[] listViewCoords = new int[2]; mRecyclerView.getLocationOnScreen(listViewCoords); int x = (int) motionEvent.getRawX() - listViewCoords[0]; int y = (int) motionEvent.getRawY() - listViewCoords[1]; View child; for (int i = 0; i < childCount; i++) { child = mRecyclerView.getChildAt(i); child.getHitRect(rect); if (rect.contains(x, y)) { mDownView = child; break; } } if (mDownView != null && mAnimatingPosition != mRecyclerView.getChildPosition(mDownView)) { mAlpha = mDownView.getAlpha(); mDownX = motionEvent.getRawX(); mDownY = motionEvent.getRawY(); mDownPosition = mRecyclerView.getChildPosition(mDownView); if (mSwipeListener.canSwipe(mDownPosition)) { mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(motionEvent); } else { mDownView = null; } } break; } case MotionEvent.ACTION_CANCEL: { if (mVelocityTracker == null) { break; } if (mDownView != null && mSwiping) { // cancel mDownView .animate() .translationX(0) .alpha(mAlpha) .setDuration(mAnimationTime) .setListener(null); } mVelocityTracker.recycle(); mVelocityTracker = null; mDownX = 0; mDownY = 0; mDownView = null; mDownPosition = ListView.INVALID_POSITION; mSwiping = false; break; } case MotionEvent.ACTION_UP: { if (mVelocityTracker == null) { break; } mFinalDelta = motionEvent.getRawX() - mDownX; mVelocityTracker.addMovement(motionEvent); mVelocityTracker.computeCurrentVelocity(1000); float velocityX = mVelocityTracker.getXVelocity(); float absVelocityX = Math.abs(velocityX); float absVelocityY = Math.abs(mVelocityTracker.getYVelocity()); boolean dismiss = false; boolean dismissRight = false; if (Math.abs(mFinalDelta) > mViewWidth / 2 && mSwiping) { dismiss = true; dismissRight = mFinalDelta > 0; } else if (mMinFlingVelocity <= absVelocityX && absVelocityX <= mMaxFlingVelocity && absVelocityY < absVelocityX && mSwiping) { // dismiss only if flinging in the same direction as dragging dismiss = (velocityX < 0) == (mFinalDelta < 0); dismissRight = mVelocityTracker.getXVelocity() > 0; } if (dismiss && mDownPosition != mAnimatingPosition && mDownPosition != ListView.INVALID_POSITION) { // dismiss final View downView = mDownView; // mDownView gets null'd before animation ends final int downPosition = mDownPosition; ++mDismissAnimationRefCount; mAnimatingPosition = mDownPosition; mDownView .animate() .translationX(dismissRight ? mViewWidth : -mViewWidth) .alpha(0) .setDuration(mAnimationTime) .setListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { performDismiss(downView, downPosition); } }); } else { // cancel mDownView .animate() .translationX(0) .alpha(mAlpha) .setDuration(mAnimationTime) .setListener(null); } mVelocityTracker.recycle(); mVelocityTracker = null; mDownX = 0; mDownY = 0; mDownView = null; mDownPosition = ListView.INVALID_POSITION; mSwiping = false; break; } case MotionEvent.ACTION_MOVE: { if (mVelocityTracker == null || mPaused) { break; } mVelocityTracker.addMovement(motionEvent); float deltaX = motionEvent.getRawX() - mDownX; float deltaY = motionEvent.getRawY() - mDownY; if (!mSwiping && Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) { mSwiping = true; mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop); } if (mSwiping) { mDownView.setTranslationX(deltaX - mSwipingSlop); mDownView.setAlpha( Math.max(0f, Math.min(mAlpha, mAlpha * (1f - Math.abs(deltaX) / mViewWidth)))); return true; } break; } } return false; }