一:前言
之前在很多项目中发现了滑动退出当前页面功能,但是并未去了解具体实现使用到了哪些,直到前不久接手的项目的也使用到了这一功能,才了解到ViewDragHelper这一强大的自定义ViewGroup神器。包括实现类似于QQ侧滑,悬浮按钮等都离不开这一神器,好记性不如烂笔头,这里记录一下学习ViewDragHelper的过程,希望大家一起成长!
what?
ViewDragHelper是什么?我们先看一下谷歌官方的解释:

立马打开我的百度翻译:

what the fuck?好吧,看到这我直接忽略百度翻译,咨询了一下英语八级的同学,得到牛逼的翻译:ViewDragHelper是编写自定义ViewGroups一个实用工具类。它定义了一组有用的操作和状态追踪,允许用户在父ViewGroup中拖动并且重新定位子View(child view)。
为什么说得到了牛逼的翻译呢,因为这个工具类牛逼啊,号称是自定义ViewGroup拖动的一个神器,比如在DrawerLayout中的一系列拖动事件都是利用VDH(ViewDragHelper,简称VDH)完成的。那么我们就一步一步来揭开它的神秘面纱~~
首先看看他的api:

好心熊已经给大家打上最简单的注释了,如果需要详细了解,还望各位同僚们动动手指,去百度!!!!

哇,看到了无数的api,那么我们先从最简单的开始吧。就是实现一个DragView继承LinearLayout,看看如何使用ViewDragHelper实现DragView吧。
第一步:新建类继承LinearLayout,实现构造方法:
public class DragView extends LinearLayout{
public DragView(Context context) {
this(context,null);
}
publicDragView(Context context,@Nullable AttributeSet attrs) {
super(context,attrs,0);
}
public DragView(Context context,@NullableAttributeSet attrs, int defStyleAttr) {
super(context,attrs,defStyleAttr);
init();
}
private void init(){};
}
那么我们如何去创建一个ViewDragHelper呢,直接new的话会发现并没有,这是因为他的构造方法私有化啦。我们观察其源码就可以发现两个获取到其实例对象的方法:

看看需要的参数都是啥,ViewGroup:也就是你真在创建的这个自定义ViewGroup——DragView,所以直接传入this即可。 cb是callBack啦,看到前面的方法介绍,大家肯定也知道cb就是用来处理各类事件触发后的回调处理。 float sensitivity:这个是敏感度值,一般传入1.0f,传入的值越大,敏感度越高。
我们还可以看到一个mTouchSlop,这个值是什么,又在哪里初始化呢?
继续追踪源码,可以先后看到如下代码:



简单理解即为应该触发移动时间的最短距离,如果小于这个距离就不触发移动控件,ViewPager控件就是利用这个距离来判断是否翻页。
额,。。咱们见好就收,回到创建ViewDragHelper,那么我们自己先创建一个试试:
在上面的init方法中创建:
private void init(){
dragHelper=ViewDragHelper.create(this,1.0f, newViewDragHelper.Callback() {
@Override
public booleantryCaptureView(Viewchild, intpointerId) {
return false;
}
});
};
传递一个cb,重写其抽象方法tryCaptureView,系统会依次列出这个父容器的子视图,你需要指定当前传入的这个视图是否可以被拖动,如果可以拖动就返回true,否则就返回false”返回两个参数,child是正在被捕捉的view,pointerid是当前按下点的id。
我们返回ture试试,。看看子View能不能滑动。
这里我们把代码补全,特别简单。
test_layout.xml:

布局文件中只有两个TextView,一个给它取了个名字。
我们想实现滑动,还必须重写两个方法:
clampViewPositionHorizontal
clampViewPositionVertical

我们 还需要拦截事件教给VDH,在OnTouchEvent中把事件交个VDH完成:

那么我们运行程序,发现两个TextView都可以拖动了。
如果我们想要给指定控件拖动呢,我们还记得tryCaptureView中的两个参数吗,可以通过child.getId() ==R.id.xxx来指定可拖动控件。
总结:我们最简单的一个ViewDragHelper的使用到此已经完成了,我们可以自己参阅源码来了解各个api的作用是什么,谢谢。
网友评论