We usually in the process of QQ, there is an effect that we can not ignore, that is the message record side swipe delete function, I believe that many people have used this function. I have to say that QQ’s interaction is really excellent. Today, let’s imitate QQ’s sideslip effect (this is itself a small effect inside the building master design, I just separate it out), first of all, let’s have a look at the Demo effect:

ItemTouchHelper

  1. RecyclerView extension (2) – ItemTouchHelper
  2. RecyclerView extension (3) – Use ItemTouchHelper and LayoutManager for sliding cards

1. An overview of the

Before explaining how the above effects are implemented, let’s take a look at some of the issues to consider:

  1. How to achieve left and right sideslip?ItemTouchHelper?ItemTouchHelperHow to achieve sideslip after not delete, but stay in a certain state.
  2. From the above renderings, we can definitely feel that sliding left and right can exceedRecyclerViewOnly after the fingers are loosened,ItemViewIt’ll just get back to the right place. Like this,overscrollHow should the effect be achieved?
  3. When it stays in the delete state, theItemViewYou can also swipe left or right (QQ seems to swipe right only at 😂). How should this effect be achieved?

In view of the above three problems, this paper will analyze in detail how to achieve. Itemtouchhelper. Callback: ItemTouchHelper.Callback: ItemTouchHelper.Callback: ItemTouchHelper.Callback Let’s start with a few methods of temTouchHelper.callback.

The method name role
getSwipeThreshold When the sideslip slides the distance /RecyclerViewIs larger than the value returned by this method, then the sideslip deletion operation is triggered. Specifically: at this timeItemViewCan do displacement animation whenItemViewTrigger when not visibleItemTouchHelpertheonSwipedMethod, and then we are inonSwipedMethod to remove the Adapter.
getSwipeEscapeVelocity If the sideslip speed is greater than the return value of this method, the sideslip deletion operation will also be triggered.
onChildDraw This approach is the core of this article. The method inItemViewIt will be called back when sliding. The sliding here includes: 1. 2.ItemViewThe displacement animation of. According toisCurrentlyActiveParameter to determine whether a finger swipe or animated slide.
clearView This approach is the core of this article. The method inItemViewAfter the slide is done, it will callback, so you want to do sideslipItemViewStop in a certain state, this method is the core point.

After understanding the above methods, now I will briefly describe the implementation method of the effect: First of all, we set the sliding distance threshold and sliding speed threshold to the maximum, to ensure that the original sideslip deletion operation will not be triggered. When the finger slides, we let it slide happily without doing anything; When the finger is released, because the speed threshold and the distance threshold are both maximum and therefore cannot be exceeded, then the ItemView will animate back to its original state, But we can’t move the ItemView according to the original rules, so we need to determine whether the sliding distance of the ItemView when the finger is released is greater than the threshold we set (whether the delete button is displayed). If it is, we will animate it to the given position, and if it is smaller, we will return to the original position.

3. The implementation

Now let’s take a formal look at the code, starting with the getSwipeThreshold and getSwipeEscapeVelocity methods:

    @Override
    public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
        return Integer.MAX_VALUE;
    }

    @Override
    public float getSwipeEscapeVelocity(float defaultValue) {
        return Integer.MAX_VALUE;
    }
Copy the code

I’m going to set it to integer.max_value. In fact, getSwipeThreshold need not be set so large, set to 1.1 should be ok, after all, it is a percentage. Now let’s look at the implementation of the onChildDraw method:

    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, floatDY, int actionState, Boolean isCurrentlyActive) {// Record the current sliding distance of ItemView for the first timeif (dX == 0) {
            mCurrentScrollX = viewHolder.itemView.getScrollX();
            mFirstInactive = true;
        }
        ifSlide (isCurrentlyActive) {/ / finger / / based on the current distance sliding viewHolder itemView. ScrollTo (mCurrentScrollX + (int)-dX, 0);
        } else{// Animation slideif (mFirstInactive) {
                mFirstInactive = false;
                mCurrentScrollXWhenInactive = viewHolder.itemView.getScrollX();
                mInitXWhenInactive = dX;
            }
            if(viewHolder. ItemView. GetScrollX () > = mDefaultScrollX) {/ / when fingers, itemView sliding distance is greater than the given threshold, then eventually will stay on the threshold, the display delete button. viewHolder.itemView.scrollTo(Math.max(mCurrentScrollX + (int)-dX, mDefaultScrollX), 0);
            } else{// We can only scale the distance here, because returning to the original position must start from the current position, Dx does not necessarily equals the sliding distance ItemView viewHolder. ItemView. ScrollTo ((int) (mCurrentScrollXWhenInactive * dx/mInitXWhenInactive), 0). }}}Copy the code

It should be noted that, in order to avoid skipping when sliding, we must slide based on the current sliding distance when manually sliding, because every time the finger slides, dx starts from 0, which means that every time the finger slides the ItemView starts from the original position. One other thing to notice is that when the finger stops sliding, we need to figure out what state the ItemView should end up in. Here the state is nothing more than two kinds, one is to delete the state, an initial state. After determining the state, we need to move the ItemView to the specified position in two ways:

  1. Implement your own animation to slide to the specified position.
  2. throughonChildDrawMethod to slide to the specified position.

Here I use the second method, the first method is relatively easy, after all, do your own animation; And the second one requires the value of dx. For details, you can see the comments on my code.

Let’s look at the implementation of the clearView method:

    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        if (viewHolder.itemView.getScrollX() > mDefaultScrollX) {
            viewHolder.itemView.scrollTo(mDefaultScrollX, 0);
        } else if (viewHolder.itemView.getScrollX() < 0) {
            viewHolder.itemView.scrollTo(0, 0);
        }
        mItemTouchStatus.onSaveItemStatus(viewHolder);
    }
Copy the code

So what clearView does is when you slide the ItemView, you do some processing, and you have to make sure that the ItemView slides to the specified location, because you’re going to have a little bit of error in the calculation, so you’re going to do some repositioning.

4. github

To help you understand, I uploaded my code to Github: SlideDeleteDemo