ItemTouchHelper源码分析(中)

来源:互联网 发布:淘宝爱奇艺会员店铺 编辑:程序博客网 时间:2024/05/16 08:02

其中最主要的是调用了select(null, ACTION_STATE_IDLE)方法,由于方法复杂,我们目前先暂不讲解。

关于onInterceptTouchEvent(),我们最后再看一下返回值,return mSelected != null;也就是说mSelected不为null的时候就返回true,这个返回值如果为true,那么就会调用 方法

onTouchEvent(RecyclerView recyclerView, MotionEvent event)

这个方法就是用于接收手指移动的事件了。

 

public void onTouchEvent(RecyclerView recyclerView, MotionEvent event) {

            mGestureDetector.onTouchEvent(event);

            if (DEBUG) {

                Log.d(TAG,

                        "on touch: x:" + mInitialTouchX + ",y:" + mInitialTouchY + ", :" + event);

            }

            if (mVelocityTracker != null) {

                mVelocityTracker.addMovement(event);

            }

            if (mActivePointerId == ACTIVE_POINTER_ID_NONE) {

                return;

            }

            final int action = MotionEventCompat.getActionMasked(event);

            final int activePointerIndex = MotionEventCompat

                    .findPointerIndex(event, mActivePointerId);

            if (activePointerIndex >= 0) {

                checkSelectForSwipe(action, event, activePointerIndex);

            }

            ViewHolder viewHolder = mSelected;

            if (viewHolder == null) {

                return;

            }

            switch (action) {

               //Part3

                case MotionEvent.ACTION_MOVE: {

                    // Find the index of the active pointer and fetch its position

                    if (activePointerIndex >= 0) {

                        updateDxDy(event, mSelectedFlags, activePointerIndex);

                        moveIfNecessary(viewHolder);

                        mRecyclerView.removeCallbacks(mScrollRunnable);

                        mScrollRunnable.run();

                        mRecyclerView.invalidate();

                    }

                    break;

                }

                case MotionEvent.ACTION_CANCEL:

                    if (mVelocityTracker != null) {

                        mVelocityTracker.clear();

                    }

                //Part4

                    // fall through

                case MotionEvent.ACTION_UP:

                    select(null, ACTION_STATE_IDLE);

                    mActivePointerId = ACTIVE_POINTER_ID_NONE;

                    break;

                case MotionEvent.ACTION_POINTER_UP: {

                    final int pointerIndex = MotionEventCompat.getActionIndex(event);

                    final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex);

                    if (pointerId == mActivePointerId) {

                        // This was our active pointer going up. Choose a new

                        // active pointer and adjust accordingly.

                        final int newPointerIndex = pointerIndex == 0 ? 1 : 0;

                        mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex);

                        updateDxDy(event, mSelectedFlags, pointerIndex);

                    }

                    break;

                }

            }

        }

 

  首先,请看Part3,:这个是onTouchEvent的核心部分.它给我们呈现的是手指移动的时候需要做的事情。

  其次,请看Part4,这个是手指离开屏幕的时候需要做的事情,当手指离开的时候做的事情和在onInterceptTouchEvent 里面介绍的一样,他们都是进行相同的操作。

  那么,Part3 里面具体都做了什么呢?

   updateDxDy(),计算的是当前touch事件移动的坐标,算法中使用了Part1中记录的位置信息。

   moveIfNecessary(),计算是否需要移动正在移动的itemRecyclerView 里面的位置,这个里面会调用一系列的Callback里面接口,通过一系列的判断决定时候需要将当前itemAdapter中的index进行修改。

   mScrollRunnable.run(),我们可以先看看mScrollRunnable的源码。

private final Runnable mScrollRunnable = new Runnable() {

        @Override

        public void run() {

            if (mSelected != null && scrollIfNecessary()) {

                if (mSelected != null) { //it might be lost during scrolling

                    moveIfNecessary(mSelected);

                }

                mRecyclerView.removeCallbacks(mScrollRunnable);

                ViewCompat.postOnAnimation(mRecyclerView, this);

            }

        }

};

    这个方法其实是一个递归调用,大家看到没有,ViewCompat.postOnAnimation(mRecyclerView, this)方法就是设置一个帧动画时间,到点就重启Runnable。而这个方法里面主要做的事情是moveIfNecessary(mSelected);这个方法在上面已经介绍过,就是移动item的位置。所以联合起来理解,就是用一个递归的方法反复的调用move来达到一个拖动效果,这个效果就是一个item移动到屏幕边境的时候,会和看不见的又存在的item进行转换位置的动效的数据部分了。

紧接着,mRecyclerView.invalidate();被调用了。

Invalidate(),将触发recyclerViewonDraw方法被调用,onDraw方法如下:

   public void onDraw(Canvas c) {

        super.onDraw(c);

 

        final int count = mItemDecorations.size();

        for (int i = 0; i < count; i++) {

            mItemDecorations.get(i).onDraw(c, this, mState);

        }

    }

这个方法会调用 mItemDecorations.get(i).onDraw(c, this, mState);ItemTouchHelper就是其中一个item,可以通过setupCallbacks()发现这一点。这个时候ItemTouchHelperonDraw方法被调用了。

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {

        // we don't know if RV changed something so we should invalidate this index.

        mOverdrawChildPosition = -1;

        float dx = 0, dy = 0;

        if (mSelected != null) {

            getSelectedDxDy(mTmpPosition);

            dx = mTmpPosition[0];

            dy = mTmpPosition[1];

        }

        mCallback.onDraw(c, parent, mSelected,

                mRecoverAnimations, mActionState, dx, dy);

    }

在这个方法里面又会调用mCallback.onDraw,当我们点击进入这个函数的时候,会发现其实它调用了Callback 类的onDraw方法,再看源码:

private void onDraw(Canvas c, RecyclerView parent, ViewHolder selected,

                List<ItemTouchHelper.RecoverAnimation> recoverAnimationList,

                int actionState, float dX, float dY) {

            final int recoverAnimSize = recoverAnimationList.size();

            for (int i = 0; i < recoverAnimSize; i++) {

                final ItemTouchHelper.RecoverAnimation anim = recoverAnimationList.get(i);

                anim.update();

                final int count = c.save();

                onChildDraw(c, parent, anim.mViewHolder, anim.mX, anim.mY, anim.mActionState,

                        false);

                c.restoreToCount(count);

            }

            if (selected != null) {

                final int count = c.save();

                onChildDraw(c, parent, selected, dX, dY, actionState, true);

                c.restoreToCount(count);

            }

        }

原创粉丝点击