背景
项目需求,要求在选择本地图片时,可对图片进行滑动选择。类似小米图库或者图库,现在很多手机系统内置图库都自带了这个功能。最后经过调研,使用自定义View解决。SlidingCheckLayout滑动选择布局,用于嵌套RecyclerView实现滑动选择功能。
效果如图所示:
最后将代码整理了一下,并上传到Jitpack。
源码
https://github.com/huangyu/SlidingCheckLayout
引用方式
在根目录:
1 | allprojects { |
添加依赖:
1 | dependencies { |
使用方法
在layout的xml中,在RecyclerView外层嵌套SlidingCheckLayout作为唯一子节点。
在App中实现SlidingCheckLayout.OnSlidingCheckListener接口即可,具体可参考Demo工程。
原理
通过onInterceptTouchEvent方法拦截滑动请求,找到起始点坐标。
1 | // 计算起始点坐标 |
RecycleView的findChildViewUnder()方法,可以十分方便返回指定位置的childView。
判断是否处于滑动状态,xTouchSlop和yTouchSlop为横向和纵向两个阈值。
1 | float xDiff = Math.*abs*(ev.getX() - startX); |
为了和RecycleView的Item点击事件不冲突,通过自定义一个判断标记isSliding,返回是否拦截滑动请求,即是否进行了滑动选择。
通过onTouchEvent处理具体的拦截逻辑。
1 | @Override |
既然是滑动,处理事件肯定是在ACTION_MOVE里。这里的inTopSpot和inBottomSpot两个标记用于计算是否滑动到顶部或者底部,用于滑动到顶部或者底部时,使用Scroller进行自动滚动。具体实现在processAutoScroll方法。
updateSelectedRange则处理滑动选择。
1 | private void updateSelectedRange(RecyclerView rv, float x, float y) { |
这里同样用findChildViewUnder方法记录结束标志,现在获取到了起始点和结束点。
1 | private void notifySelectRangeChange() { |
notifySelectRangeChange为核心处理逻辑,通过当前滑动的起始点和终点计算中间滑动的范围并回调给调用方。
这里自定义了一个回调接口类:
1 | public interface OnSlidingCheckListener { |
最后外部使用回调对起始点至终点部分进行选择处理。
1 | scl.setOnSlidingCheckListener(new SlidingCheckLayout.OnSlidingCheckListener() { |
Done.