/** Adds new items when adapter is modified */ public void resetItems() { if (swipeRecyclerView.getAdapter() != null) { int count = swipeRecyclerView.getAdapter().getItemCount(); for (int i = opened.size(); i <= count; i++) { opened.add(false); openedRight.add(false); checked.add(false); } } }
/** * Reset the state of front view when the it's recycled by ListView * * @param frontView view to re-draw */ protected void reloadSwipeStateInView(View frontView, int position) { if (!opened.get(position)) { setTranslationX(frontView, 0.0f); } else { if (openedRight.get(position)) { setTranslationX(frontView, swipeRecyclerView.getWidth()); } else { setTranslationX(frontView, -swipeRecyclerView.getWidth()); } } }
/** Unselected choice state in item */ protected void unselectedChoiceStates() { int start = mLayoutManager.findFirstVisibleItemPosition(); int end = mLayoutManager.findLastVisibleItemPosition(); for (int i = 0; i < checked.size(); i++) { if (checked.get(i) && i >= start && i <= end) { reloadChoiceStateInView( swipeRecyclerView.getChildAt(i - start).findViewById(swipeFrontView), i); } checked.set(i, false); } swipeRecyclerView.onChoiceEnded(); returnOldActions(); }
/** * Will delete all pending dismisses. Will call callback onDismiss for all pending dismisses. Will * reset all cell height to originalHeight. * * @param originalHeight is the height of the cell before animation. */ private void removePendingDismisses(int originalHeight) { // No active animations, process all pending dismisses. // Sort by descending position Collections.sort(pendingDismisses); int[] dismissPositions = new int[pendingDismisses.size()]; for (int i = pendingDismisses.size() - 1; i >= 0; i--) { dismissPositions[i] = pendingDismisses.get(i).position; } swipeRecyclerView.onDismiss(dismissPositions); ViewGroup.LayoutParams lp; for (PendingDismissData pendingDismiss : pendingDismisses) { // Reset view presentation if (pendingDismiss.view != null) { setAlpha(pendingDismiss.view, 1f); setTranslationX(pendingDismiss.view, 0); lp = pendingDismiss.view.getLayoutParams(); lp.height = originalHeight; pendingDismiss.view.setLayoutParams(lp); } } resetPendingDismisses(); }
/** * Constructor * * @param swipeRecyclerView SwipeListView * @param swipeFrontView front view Identifier * @param swipeBackView back view Identifier */ public SwipeRecyclerTouchListener( SwipeRecyclerView swipeRecyclerView, int swipeFrontView, int swipeBackView) { this.swipeFrontView = swipeFrontView; this.swipeBackView = swipeBackView; ViewConfiguration vc = ViewConfiguration.get(swipeRecyclerView.getContext()); slop = vc.getScaledTouchSlop(); minFlingVelocity = vc.getScaledMinimumFlingVelocity(); maxFlingVelocity = vc.getScaledMaximumFlingVelocity(); configShortAnimationTime = swipeRecyclerView .getContext() .getResources() .getInteger(android.R.integer.config_shortAnimTime); animationTime = configShortAnimationTime; this.swipeRecyclerView = swipeRecyclerView; }
/** * Open item * * @param position Position of list */ protected void openAnimate(int position) { final View child = swipeRecyclerView .getChildAt(position - mLayoutManager.findFirstVisibleItemPosition()) .findViewById(swipeFrontView); if (child != null) { openAnimate(child, position); } }
/** Close all opened items */ void closeOpenedItems() { if (opened != null) { int start = mLayoutManager.findFirstVisibleItemPosition(); int end = mLayoutManager.findLastVisibleItemPosition(); for (int i = start; i <= end; i++) { if (opened.get(i)) { closeAnimate(swipeRecyclerView.getChildAt(i - start).findViewById(swipeFrontView), i); } } } }
/** * Swap choice state in item * * @param position position of list */ private void swapChoiceState(int position) { int lastCount = getCountSelected(); boolean lastChecked = checked.get(position); checked.set(position, !lastChecked); int count = lastChecked ? lastCount - 1 : lastCount + 1; if (lastCount == 0 && count == 1) { swipeRecyclerView.onChoiceStarted(); closeOpenedItems(); setActionsTo(SwipeRecyclerView.SWIPE_ACTION_CHOICE); } if (lastCount == 1 && count == 0) { swipeRecyclerView.onChoiceEnded(); returnOldActions(); } // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // swipeListView.setItemChecked(position, !lastChecked); // } swipeRecyclerView.onChoiceChanged(position, !lastChecked); reloadChoiceStateInView(frontView, position); }
private void closeOtherOpenedItems() { if (opened != null && downPosition != SwipeRecyclerView.NO_POSITION) { int start = mLayoutManager.findFirstVisibleItemPosition(); int end = mLayoutManager.findLastVisibleItemPosition(); for (int i = start; i <= end; i++) { if (opened.get(i) && i != downPosition) { closeAnimate(swipeRecyclerView.getChildAt(i - start).findViewById(swipeFrontView), i); } } } }
/** * Close item * * @param position Position of list */ protected void closeAnimate(int position) { if (swipeRecyclerView != null) { int firstVisibleChildPosition = mLayoutManager.findFirstVisibleItemPosition(); final View childContainer = swipeRecyclerView.getChildAt(position - firstVisibleChildPosition); if (childContainer != null) { final View child = childContainer.findViewById(swipeFrontView); if (child != null) { closeAnimate(child, position); } } } }
/** * Dismiss an item. * * @param position is the position of the item to delete. * @return 0 if the item is not visible. Otherwise return the height of the cell to dismiss. */ protected int dismiss(int position) { opened.remove(position); checked.remove(position); int start = mLayoutManager.findFirstVisibleItemPosition(); int end = mLayoutManager.findLastVisibleItemPosition(); View view = swipeRecyclerView.getChildAt(position - start); ++dismissAnimationRefCount; if (position >= start && position <= end) { performDismiss(view, position, false); return view.getHeight(); } else { pendingDismisses.add(new PendingDismissData(position, null)); return 0; } }
/** * Moves the view * * @param deltaX delta */ public void move(float deltaX) { swipeRecyclerView.onMove(downPosition, deltaX); float posX = ViewHelper.getX(frontView); if (opened.get(downPosition)) { posX += openedRight.get(downPosition) ? -viewWidth + rightOffset : viewWidth - leftOffset; } if (posX > 0 && !swipingRight) { if (SwipeRecyclerView.DEBUG) { Log.d(SwipeRecyclerView.TAG, "change to right"); } swipingRight = !swipingRight; swipeCurrentAction = swipeActionRight; if (swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { backView.setVisibility(View.GONE); } else { backView.setVisibility(View.VISIBLE); } } if (posX < 0 && swipingRight) { if (SwipeRecyclerView.DEBUG) { Log.d(SwipeRecyclerView.TAG, "change to left"); } swipingRight = !swipingRight; swipeCurrentAction = swipeActionLeft; if (swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { backView.setVisibility(View.GONE); } else { backView.setVisibility(View.VISIBLE); } } if (swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_DISMISS) { setTranslationX(parentView, deltaX); setAlpha(parentView, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / viewWidth))); } else if (swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { if ((swipingRight && deltaX > 0 && posX < DISPLACE_CHOICE) || (!swipingRight && deltaX < 0 && posX > -DISPLACE_CHOICE) || (swipingRight && deltaX < DISPLACE_CHOICE) || (!swipingRight && deltaX > -DISPLACE_CHOICE)) { setTranslationX(frontView, deltaX); } } else { setTranslationX(frontView, deltaX); } }
/** @see View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent) */ @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (!isSwipeEnabled()) { return false; } if (viewWidth < 2) { viewWidth = swipeRecyclerView.getWidth(); } switch (MotionEventCompat.getActionMasked(motionEvent)) { case MotionEvent.ACTION_DOWN: { if (paused && downPosition != ListView.INVALID_POSITION) { return false; } swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_NONE; int childCount = swipeRecyclerView.getChildCount(); int[] listViewCoords = new int[2]; swipeRecyclerView.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 = swipeRecyclerView.getChildAt(i); child.getHitRect(rect); int childPosition = swipeRecyclerView.getChildPosition(child); // dont allow swiping if this is on the header or footer or IGNORE_ITEM_VIEW_TYPE or // enabled is false on the adapter // boolean allowSwipe = swipeListView.getAdapter().isEnabled(childPosition) && // swipeListView.getAdapter().getItemViewType(childPosition) >= 0; boolean allowSwipe = true; if (allowSwipe && rect.contains(x, y)) { setParentView(child); setFrontView(child.findViewById(swipeFrontView), childPosition); downX = motionEvent.getRawX(); downPosition = childPosition; frontView.setClickable(!opened.get(downPosition)); frontView.setLongClickable(!opened.get(downPosition)); velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(motionEvent); if (swipeBackView > 0) { setBackView(child.findViewById(swipeBackView)); } break; } } view.onTouchEvent(motionEvent); return true; } case MotionEvent.ACTION_UP: { if (velocityTracker == null || !swiping || downPosition == ListView.INVALID_POSITION) { break; } float deltaX = motionEvent.getRawX() - downX; velocityTracker.addMovement(motionEvent); velocityTracker.computeCurrentVelocity(1000); float velocityX = Math.abs(velocityTracker.getXVelocity()); if (!opened.get(downPosition)) { if (swipeMode == SwipeRecyclerView.SWIPE_MODE_LEFT && velocityTracker.getXVelocity() > 0) { velocityX = 0; } if (swipeMode == SwipeRecyclerView.SWIPE_MODE_RIGHT && velocityTracker.getXVelocity() < 0) { velocityX = 0; } } float velocityY = Math.abs(velocityTracker.getYVelocity()); boolean swap = false; boolean swapRight = false; if (minFlingVelocity <= velocityX && velocityX <= maxFlingVelocity && velocityY * 2 < velocityX) { swapRight = velocityTracker.getXVelocity() > 0; if (SwipeRecyclerView.DEBUG) { Log.d( SwipeRecyclerView.TAG, "swapRight: " + swapRight + " - swipingRight: " + swipingRight); } if (swapRight != swipingRight && swipeActionLeft != swipeActionRight) { swap = false; } else if (opened.get(downPosition) && openedRight.get(downPosition) && swapRight) { swap = false; } else if (opened.get(downPosition) && !openedRight.get(downPosition) && !swapRight) { swap = false; } else { swap = true; } } else if (Math.abs(deltaX) > viewWidth / 2) { swap = true; swapRight = deltaX > 0; } generateAnimate(frontView, swap, swapRight, downPosition); if (swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { swapChoiceState(downPosition); } velocityTracker.recycle(); velocityTracker = null; downX = 0; // change clickable front view // if (swap) { // frontView.setClickable(opened.get(downPosition)); // frontView.setLongClickable(opened.get(downPosition)); // } swiping = false; break; } case MotionEvent.ACTION_MOVE: { if (velocityTracker == null || paused || downPosition == ListView.INVALID_POSITION) { break; } velocityTracker.addMovement(motionEvent); velocityTracker.computeCurrentVelocity(1000); float velocityX = Math.abs(velocityTracker.getXVelocity()); float velocityY = Math.abs(velocityTracker.getYVelocity()); float deltaX = motionEvent.getRawX() - downX; float deltaMode = Math.abs(deltaX); int swipeMode = this.swipeMode; int changeSwipeMode = swipeRecyclerView.changeSwipeMode(downPosition); if (changeSwipeMode >= 0) { swipeMode = changeSwipeMode; } if (swipeMode == SwipeRecyclerView.SWIPE_MODE_NONE) { deltaMode = 0; } else if (swipeMode != SwipeRecyclerView.SWIPE_MODE_BOTH) { if (opened.get(downPosition)) { if (swipeMode == SwipeRecyclerView.SWIPE_MODE_LEFT && deltaX < 0) { deltaMode = 0; } else if (swipeMode == SwipeRecyclerView.SWIPE_MODE_RIGHT && deltaX > 0) { deltaMode = 0; } } else { if (swipeMode == SwipeRecyclerView.SWIPE_MODE_LEFT && deltaX > 0) { deltaMode = 0; } else if (swipeMode == SwipeRecyclerView.SWIPE_MODE_RIGHT && deltaX < 0) { deltaMode = 0; } } } if (deltaMode > slop && swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_NONE && velocityY < velocityX) { swiping = true; swipingRight = (deltaX > 0); if (SwipeRecyclerView.DEBUG) { Log.d( SwipeRecyclerView.TAG, "deltaX: " + deltaX + " - swipingRight: " + swipingRight); } if (opened.get(downPosition)) { swipeRecyclerView.onStartClose(downPosition, swipingRight); swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_REVEAL; } else { if (swipingRight && swipeActionRight == SwipeRecyclerView.SWIPE_ACTION_DISMISS) { swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_DISMISS; } else if (!swipingRight && swipeActionLeft == SwipeRecyclerView.SWIPE_ACTION_DISMISS) { swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_DISMISS; } else if (swipingRight && swipeActionRight == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_CHOICE; } else if (!swipingRight && swipeActionLeft == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_CHOICE; } else { swipeCurrentAction = SwipeRecyclerView.SWIPE_ACTION_REVEAL; } swipeRecyclerView.onStartOpen(downPosition, swipeCurrentAction, swipingRight); } swipeRecyclerView.requestDisallowInterceptTouchEvent(true); MotionEvent cancelEvent = MotionEvent.obtain(motionEvent); cancelEvent.setAction( MotionEvent.ACTION_CANCEL | (MotionEventCompat.getActionIndex(motionEvent) << MotionEventCompat.ACTION_POINTER_INDEX_SHIFT)); swipeRecyclerView.onTouchEvent(cancelEvent); if (swipeCurrentAction == SwipeRecyclerView.SWIPE_ACTION_CHOICE) { backView.setVisibility(View.GONE); } } if (swiping && downPosition != ListView.INVALID_POSITION) { if (opened.get(downPosition)) { deltaX += openedRight.get(downPosition) ? viewWidth - rightOffset : -viewWidth + leftOffset; } move(deltaX); return true; } break; } } if (onlyOneOpenedWhenSwipe) { closeOtherOpenedItems(); view.onTouchEvent(motionEvent); return true; } return false; }