源码分析 ItemTouchHelper手势的入口 (OnInterceptTouchEvent onLongPress等)

本文探讨了Android中的ItemTouchHelper如何处理手势,它作为RecyclerView的ItemDecoration实现,源于ViewDragHelper。主要关注长按、垂直滑动超过touchSlop和恢复动画时的手势入口,这些入口在OnInterceptTouchEvent中被触发,并通过GestureDetector的长按回调进行处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ItemTouchHelper是v7包RecyclerView的ItemDecoration接口的一个实现,其前身是v4包的ViewDragHelper(可在任意ViewGroup中使用)在DrawerLayout、SlidingPaneLayout源码中都有应用。

两者使用方法也很类似,都是实现各自的Callback

ItemTouchHelper手势的实现都在匿名内部类mOnItemTouchListener中实现,

private final OnItemTouchListener mOnItemTouchListener
            = new OnItemTouchListener()

与RecyclerView的绑定,则在attachToRecyclerView方法中的setupCallbacks()中

add到RV中

    /**
     * Attaches the ItemTouchHelper to the provided RecyclerView. If TouchHelper is already
     * attached to a RecyclerView, it will first detach from the previous one. You can call this
     * method with {@code null} to detach it from the current RecyclerView.
     *
     * @param recyclerView The RecyclerView instance to which you want to add this helper or
     *                     {@code null} if you want to remove ItemTouchHelper from the current
     *                     RecyclerView.
     */
    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
        if (mRecyclerView == recyclerView) {
            return; // nothing to do
        }
        if (mRecyclerView != null) {
            destroyCallbacks(); //避免重复绑定
        }
        mRecyclerView = recyclerView;
        if (mRecyclerView != null) {
            final Resources resources = recyclerView.getResources();
            mSwipeEscapeVelocity = resources
                    .getDimension(R.dimen.item_touch_helper_swipe_escape_velocity);
            mMaxSwipeVelocity = resources
                    .getDimension(R.dimen.item_touch_helper_swipe_escape_max_velocity);
            setupCallbacks(); //初始化 setup
        }
    }

    private void setupCallbacks() {
        ViewConfiguration vc = ViewConfiguration.get(mRecyclerView.getContext());
        mSlop = vc.getScaledTouchSlop(); //初始化TouchSlop
        mRecyclerView.addItemDecoration(this);  //绑定Callback.OnDraw供实现onChildDraw
        mRecyclerView.addOnItemTouchListener(mOnItemTouchListener); //绑定手势监听
        mRecyclerView.addOnChildAttachStateChangeListener(this); 
        initGestureDetector();
    }

    private void destroyCallbacks() {
        mRecyclerView.removeItemDecoration(this);  //避免重复绑定
        mRecyclerView.removeOnItemTouchListener(mOnItemTouchListener); //避免重复绑定
        mRecyclerView.removeOnChildAttachStateChangeListener(this); //避免重复绑定
        // clean all attached
        final int recoverAnimSize = mRecoverAnimations.size();
        for (int i = recoverAnimSize - 1; i >= 0; i--) {
            final RecoverAnimation recoverAnimation = mRecoverAnimations.get(0);
            mCallback.clearView(mRecyclerView, recoverAnimation.mViewHolder);
        }
        mRecoverAnimations.clear();
        mOverdrawChild = null;
        mOverdrawChildPosition = -1;
        releaseVelocityTracker();
    }

进入正题

严格的说,ItemTouchHelper的手势正式接管方法是select()方法,而通过手势开始(达到某种条件)而进入select的入口总共3个

1、长按

2、与rv垂直方向的swipe移动(超过touchSlop的Move)

3、按下一个正在做恢复动画的vh(对RecoverAnimation没做完的vh触发Down事件)

既然是手势接管,毫无疑问,这些入口的入口一定来自mOnItemTouchListener的OnInterceptTouchEvent方法

        @Override
        public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) {
            mGestureDetector.onTouchEvent(event);//主要实现onLongPress的监听  
这里就是 入口1,下有对于ItemTouchHelperGestureListener的onLongPress具体分析

    //如果是个长按 那么拦截短路掉RV自己的滑动
    //并判定Down选中的vh ItemTouchHelper正式接管 
            if (DEBUG) {
                Log.d(TAG, "intercept: x:" + event.getX() + ",y:" + event.getY() + ", " + event);
            }
            final int 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值