3

I need to swipe an item at the beginning, or did a full swipe, or stopped in current point. As in the Yandex mail. I was tring to do setLeft(dx) and setRight(dx) but that's not what I need

I have class

ItemTouchHelperCallback extends ItemTouchHelper.Callback 

and inside i override method

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    View itemView = viewHolder.itemView;

    // not sure why, but this method get's called for viewholder that are already swiped away
    if (viewHolder.getAdapterPosition() == -1) {
        // not interested in those
        return;
    }

    float height = (float) itemView.getBottom() - (float) itemView.getTop();
    float width = height / 3;
    float temdX=0;
    Bitmap icon;
    if(dX > 0 || lastdX>0){

        //try stop item while back in dx=0, but workin only while i debug
        if(lastdX>=100 && dX==0 &&lastdX!=0 &&lastdX!=-720)
        {
            dX=100;
            isCurrentlyActive=true;

        }
        lastdX=dX;
        itemView.setLeft((int) dX);
        p.setColor(Color.GREEN);
        RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom());
        c.drawRect(background,p);
        icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_y);
        RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width, (float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width);
        c.drawBitmap(icon, null, icon_dest, p);


    } else if(lastdX<0 || dX<0) {
        if(lastdX<=-100 && dX==0 &&lastdX!=0 &&lastdX!=720)
        {
            dX=-100;
            //itemView.setTranslationX(-200);

            isCurrentlyActive=true;
        }
        lastdX=dX;
        itemView.setRight((int)(dX));
        p.setColor(Color.RED);
        RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom());
        c.drawRect(background,p);

        icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_x);
        RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width, (float) itemView.getRight() - width,(float)itemView.getBottom() - width);
        c.drawBitmap(icon,null,icon_dest,p);

    }
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
Toxa
  • 33
  • 3

1 Answers1

2

I needed to do something similar and at the beginning I also thought to use the callbacks provided in the ItemTouchHelper. It turned out it's not the right approach.

If you want to stop (or in general to control) the translation of the view during the swipe, you need to be able to modify and save the value of the displacement dX. If you use the ItemTouchHelper, this value is controlled outside the available callbacks.

The solution for me was the implementation of the swipe with a custom touchListener, attached in the view holder of the recycler view. You can find an example of the basic implementation here. In case you need to consider the click on the item, remember you need to implement this in the touchListener as well.

I hope this is somehow helpful.

EDIT Here a snippet of a custom ItemTouchListener. The listener is simplified and shows only code to handle the translation on the view during swipe. In order to stop swipe, just implement limit logic on translationX under ACTION_MOVE.

import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;

public class ItemTouchListener implements View.OnTouchListener {
    private int mSlop;
    private View mView;
    private float mDownX, mDownY;
    private boolean mSwiping;
    private int mSwipingSlop;
    private VelocityTracker mVelocityTracker;
    private float mTranslationX;

    public ItemTouchListener(View view) {
        ViewConfiguration vc = ViewConfiguration.get(view.getContext());
        mSlop = vc.getScaledTouchSlop();
        mView = view;
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        // offset because the view is translated during swipe
        motionEvent.offsetLocation(mTranslationX, 0);
        switch (motionEvent.getActionMasked()) {
            case MotionEvent.ACTION_DOWN: {
                mDownX = motionEvent.getRawX();
                mDownY = motionEvent.getRawY();
                return true;
            }
            case MotionEvent.ACTION_UP: {

                // if needed, implement part of limit swipe logic also here

                if (mVelocityTracker == null) {
                    break;
                }
                mVelocityTracker.addMovement(motionEvent);
                mVelocityTracker.computeCurrentVelocity(1000);
                mVelocityTracker.recycle();
                mVelocityTracker = null;
                mTranslationX = 0;
                mDownX = 0;
                mDownY = 0;
                mSwiping = false;
                break;
            }
            case MotionEvent.ACTION_CANCEL: {
                if (mVelocityTracker == null) {
                    break;
                }
                mVelocityTracker.recycle();
                mVelocityTracker = null;
                mTranslationX = 0;
                mDownX = 0;
                mDownY = 0;
                mSwiping = false;
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                if (mVelocityTracker == null) {
                    break;
                }
                mVelocityTracker.addMovement(motionEvent);
                float deltaX = motionEvent.getRawX() - mDownX;
                float deltaY = motionEvent.getRawY() - mDownY;
                if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
                    mSwiping = true;
                    mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop);
                    // cancel view's touch
                    MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
                    cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
                            (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
                    cancelEvent.recycle();
                }
                if (mSwiping) {

                    // limit deltaX here: this will keep the swipe up to desired point 

                    mTranslationX = deltaX;
                    mView.setTranslationX(deltaX - mSwipingSlop);
                    return true;
                }
                break;
            }
        }
        return false;
    }
}
Rosso
  • 146
  • 1
  • 8
  • @RikvanVelzen please check the edited answer: I added a code snippet, it is the implementation of a custom touch listener and it shows the basic idea of the solution – Rosso Aug 23 '18 at 11:03
  • how to use it ? – Bawa Feb 05 '19 at 12:37