【问题标题】:How to stop swipe at some point in ItemTouchHelpers?如何在 ItemTouchHelpers 的某个点停止滑动?
【发布时间】:2018-08-23 18:58:35
【问题描述】:

我需要在开始时滑动一个项目,或者完全滑动,或者在当前点停止。就像在 Yandex 邮件中一样。我打算做setLeft(dx) 和setRight(dx) 但这不是我需要的

我有课

ItemTouchHelperCallback extends ItemTouchHelper.Callback 

在里面我覆盖了方法

@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);
}

【问题讨论】:

    标签: java android android-layout android-recyclerview swipe


    【解决方案1】:

    我需要做一些类似的事情,一开始我还想使用 ItemTouchHelper 中提供的回调。事实证明这不是正确的方法。

    如果您想在滑动期间停止(或一般控制)视图的平移,您需要能够修改并保存位移 dX 的值。如果您使用 ItemTouchHelper,则此值在可用回调之外进行控制。

    我的解决方案是使用自定义 touchListener 实现滑动,附加在回收器视图的视图持有者中。您可以找到基本实现here 的示例。如果您需要考虑对项目的点击,请记住您还需要在 touchListener 中实现这一点。

    我希望这会有所帮助。

    编辑 这里是自定义 ItemTouchListener 的 sn-p。侦听器被简化并且仅显示在滑动期间处理视图上的翻译的代码。为了停止滑动,只需在 ACTION_MOVE 下的 translationX 上实现限制逻辑。

    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;
        }
    }
    

    【讨论】:

    • @RikvanVelzen 请检查编辑的答案:我添加了一个代码 sn-p,它是自定义触摸侦听器的实现,它显示了解决方案的基本思想
    • 怎么用?
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多