Android recyclerview源码分析(二)

来源:互联网 发布:d3.js 实战手册 pdf 编辑:程序博客网 时间:2024/06/01 07:34

这篇文章分析这3个类


这3个类是和列表item的drag和swipe手势有关的类,通过这3个类可实现类似dragsortlistview的功能。

先看下用法

ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);mItemTouchHelper = new ItemTouchHelper(callback);mItemTouchHelper.attachToRecyclerView(recyclerView);

附上高手写的demo链接

https://github.com/iPaulPro/Android-ItemTouchHelper-Demo

其中SimpleItemTouchHelperCallback是继承ItemTouchHelper.Callback

那我们从attachToRecyclerView这个方法开始分析

public void attachToRecyclerView(RecyclerView recyclerView) {    if (mRecyclerView == recyclerView) {        return; // nothing to do    }    if (mRecyclerView != null) {        destroyCallbacks();    }    mRecyclerView = recyclerView;    if (mRecyclerView != null) {        setupCallbacks();    }}
最后是调用setupCallbacks进行一些初始化工作




private void setupCallbacks() {    ViewConfiguration vc = ViewConfiguration.get(mRecyclerView.getContext());    mSlop = vc.getScaledTouchSlop();    mRecyclerView.addItemDecoration(this);//增加ItemDecoration监听    mRecyclerView.addOnItemTouchListener(mOnItemTouchListener);//item swipe手势监听    mRecyclerView.addOnChildAttachStateChangeListener(this);//子view attach和dettach的监听    initGestureDetector();//初始化drag手势监听}

一、初始化这些监听和ItemTouchHelper内部的一个类息息相关,那就是ItemTouchHelper.Callback,这个Callback

1.初始化sUICallback 

static {    if (Build.VERSION.SDK_INT >= 21) {        sUICallback = new ItemTouchUIUtilImpl.Lollipop();    } else if (Build.VERSION.SDK_INT >= 11) {        sUICallback = new ItemTouchUIUtilImpl.Honeycomb();    } else {        sUICallback = new ItemTouchUIUtilImpl.Gingerbread();    }}

ItemTouchUIUtilImpl主要有一下这些方法

1.1onDraw 设置 view 的x、y轴的偏移量

1.2onSelected  不同的系统对应不同的实现

1.3clearView 则是清除 onDraw 、onSelected  做的事情


2.设置哪些类型的手势是enabled 

例如:

isItemViewSwipeEnabled 是否可以swipe操作
isLongPressDragEnabled 是否可以drag操作

可以继承ItemTouchHelper.Callback复写这两个方法控制这两个手势是否enable


3.控制drag和swipe手势的方向,例如上下的是drag行为,左右的是swipe行为

getMovementFlags 子类重写,控制每个手势的方向

makeMovementFlags 在一个int值上保存两个手势相关的值,类似android view绘制中makemesure方法


4.当子view被drag时,有两个方法相关

4.1会回调onMove方法,不过是个空实现

4.2当onMove返回true时,会回调onMoved,这个方法能确保被drag的view不会离开recyclerview的边界


5.控制哪些子view可以拖动

5.1canDropOver 空实现

5.2chooseDropTarget 这个方法主要是判断被drag的view应不应该替换被覆盖的那个view,他们俩是否该交换位置


6.当子view处在swipe手势之后

6.1onSwiped  是个空实现,使用者重写可以对adapter的数据进行操作


二、mOnItemTouchListener

这个监听是用来分发drag和swipe事件的

2.1mOnItemTouchListener中  mGestureDetector.onTouchEvent(event); 这句代码是将事件传递给ItemTouchHelperGestureListener.onLongPress()方法

在初始化的时候这个方法就是drag的监听

private void initGestureDetector() {    if (mGestureDetector != null) {        return;    }    mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(),            new ItemTouchHelperGestureListener());}

2.2

if (index >= 0) {    checkSelectForSwipe(action, event, index);}
这段代码就是分发swipe事件的


三、真正执行drag和swipe手势的方法

其实无论drag是swipe,最后都要经过select方法,只不过传的参数不同


1.drag

select(viewHolder, ACTION_STATE_DRAG);


2.swipe

select(vh, ACTION_STATE_SWIPE);


那接下来分析下select方法里做了啥

关键代码这一句

mRecyclerView.invalidate();
调用这句代码后会通知RecyclerView 的OnDraw方法


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

最后还是会CallBack里的onDraw方法

最后总结一下select方法的调用流程,

ItemTouchHelperGestureListener.onLongPress-->select-->Callback.onDraw-->Callback.onChildDraw-->ItemTouchUIUtilImpl.onDraw


select方法其实只是控制了子view的一个偏移位置 ,Callback里的其他方法也有各自调用的时机。看Callback方法说明对应的去看就能理顺ItemTouchHelper里面所做的事情







0 0
原创粉丝点击