ViewDragHelper
一个拖拽实现的帮助类,存在于v4包中,对于实现简单的拖拽简直不要太简单;再也不用去重写onTouch()了;
官网API https://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.html
该类主要用于拖拽view的实现,例如侧滑菜单时候的左右拖拽或者上下拖拽
使用方法
创建 ViewDragHelper实例
1 | ViewDragHelper create (ViewGroup forParent, |
- 参数1 要使用DragHelper的布局
- 参数2 灵敏度,值越大越灵敏,1.0属于正常
- 参数3 回调,这里是主要阵地
事件拦截于处理
重写布局的 onInterceptTouchEvent()方法 ,ViewDragHelper会自行判断是否需要拦截事件
1 | @Override |
重写布局的 onTouchEvent() 处理拦截的事件
1 | @Override |
如果需要滑动动画 重写
computeScroll()
1 | /** |
前面在创建ViewDragHelper的时候用到了一个Callback,其实主要是在这里添加自己的逻辑,主要介绍一下这个类
这是一个抽象类,我们必须要实现的方法只有一个
tryCaptureView()
1 | public abstract boolean tryCaptureView(View child, int pointerId); |
- 参数1 准备捕获的子view
- 参数2 准备捕获的指针ID
该方法的返回值决定了ViewDragHelper是否要捕获这个view;如果返回false就不捕获;
说的一下我的思路吧,我在父布局中持有了需要拖拽处理的子view的引用,如果捕获的view是我持有的view就返回true,捕获这次事件
1 | /** |
如果你需要处理水平拖拽,重写
clampViewPositionHorizontal()即可,该方法返回值就是view拖拽后的坐标值;默认是不处理的;
下面是我的实现,为了防止拖拽出屏幕做了简单处理
1 | /** |
如果需要处理垂直拖拽,重写
clampViewPositionVertical();该方法和上面的那个方法一样,返回值就是view拖拽后的坐标值;默认不处理;
1 | /** |
可以从
onViewDragStateChanged()方法中得到ViewDragHelper的状态变化
1 | @Override |
当子view的位置发生变化会触发
onViewPositionChanged()方法
1 | /** |
拖动动作停止,可以从
onViewReleased()中得到速度信息
1 | /** |
我用到的就这些,就介绍这些吧 ,
实现了一个可以自由拖动的layout 看Demo中的DragLayout ; https://github.com/sky-mxc/AndroidDemo/tree/master/drag
侧滑菜单实现
以前写过一个侧滑菜单,思路是重写 ListView或者RecycleView 的onTouch事件,判断根据坐标点判断找到子view,然后让子view滑动,从而实现的侧滑。感觉比较麻烦。今天说一下另外一个思路,
写一个通用的布局,例如一个LineaLayout,里面定义两个Group,一个是item内容,另一个是Item 菜单;在LineaLayout内部定义一个ViewDragHelper来处理拖动事件。ViewDragHelper会将拖动事件处理好,我们只需要在callback中处理简单的逻辑就好。
写一个SwipeLayout 继承自 LineaLayout; 在构造时就创建好 DragHelper
1 | public SwipeItemLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { |
加载完毕布局之后,拿到两个item,一个内容,一个菜单
1 | @Override |
事件交由 DragHelper处理
1 | @Override |
要在callback中使用动画
1 | /** |
主要逻辑就在callback中处理
tryCaptureView() 如果拖动的时内容或者菜单就捕获此次多动
1 | @Override |
因为实现的是侧滑菜单,这里只处理 水平拖动就好,注释写的很清楚了
1 |
|
当view 被拖动的时候,另一个view跟随被拖动的view一起移动
1 | @Override |
当滑动结束后,可以根据滑动的速度或者滑动的距离来决定是否要打开或者关闭菜单;具体思路 注释已经很清楚了
1 | @Override |
为了滑动更加灵敏,在左右滑动item时,禁止父布局的上下滑动
在onTouch中 判断滑动距离,超过一定范围就不让父布局处理;getParent().requestDisallowInterceptTouchEvent(true);
1 | @Override |
贴一下代码,完整Demo看GitHub https://github.com/sky-mxc/AndroidDemo/tree/master/drag
1 | /** |