通过我们来处理自定义ViewGroup中子View滑动时,我们都是去通过事件拦截以及在onTouchEvent方法中进行手势判断,加速度检测等。
在官方的V4提供了ViewDragHelper来帮助我们方便的编写自定义ViewGroup时处理子View的滑动等相关的操作处理
代码演示:
public class CustomViewGroup extends ViewGroup {
View childView_1; //子View1
View childView_2; //子View2
ViewDragHelper viewDragHelper;
public CustomViewGroup(Context context) {
super(context);
// 第一个参数为this,表示该类生成的对象,是ViewDragHelper的拖动处理对象,必须为ViewGroup。
//第二个参数1.0f是敏感度参数参数越大越敏感,默认就是1.0f。
//第三个参数回调接口,是ViewDragHelper与View交互的桥梁
viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
/**
*通过DragHelperCallback的tryCaptureView方法的返回值可以决定一个parentview中哪个子view可以拖动,
*
* @param child
* @param pointerId
* @return
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
//return child==childView_1; 如果如此 设置 只有 childView_1可以被ViewDragHelper控制
return true; //所有View都可以
//有人问 想 控制两个怎么办
//return child == view1 || child == view2 >>>>> 484傻 ,其实是我问的
}
/**
*该方法用来处理水平方向的滑动事件,返回目的值即可,但是为了处理例如边界情况,需要考虑到对象本身的边界值
* @param child 需要被处理的对象 可以用此来判断(eg 只允许View1垂直滑动 ,判断一下,如果是view1我就不做任何操作不就行了么)
* @param left 目的值(应该是以左边的点为依据)
* @param dx
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
int left_bound = getPaddingLeft(); //左边的边界值
int right_bound = getWidth() - getPaddingRight() - child.getWidth();//右边的边界值
//这真是个有趣的表达式 第一步如果是左边部分的话,肯定是取值比 左边界要大,
// 右边部分的话(肯定比左边界大了,内部的值Max取到的肯定是 left),取到的值要比右边界小
//主要是为了 视图越界 呈现在手机窗口的外面了
return Math.min(Math.max(left, left_bound), right_bound);
}
/*
* 这里没有什么不同 只是垂直方向的罢了
* */
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
int top_bound = getPaddingTop();//上边界
int bottom_bound = getHeight() - getPaddingBottom() - child.getHeight();//下边界
return Math.min(Math.max(top, top_bound), bottom_bound);
}
/**
* 当设置了边缘滑动事件的时候,一旦事件发生,该方法就会被回调,要是想要相关View跟着运动需要在代码中执行
* @param edgeFlags 边缘的滑动标志
* @param pointerId
*/
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
//如此 第一个View就会跟着边缘事件进行 触发操作了
viewDragHelper.captureChildView(childView_1, pointerId);
}
});
//如果你想要处理左右边缘的滑动事件 可以通过以下设置 >>例如设置左边缘,如果想要监听到相关事件还需要重写回调中的一个方法
//onEdgeDragStarted()
viewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//该方法内部已经对相应的事件进行了过滤,至此直接将事件交给ViewDragHelper返回即可
return viewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//将事件拿到
viewDragHelper.processTouchEvent(event);
//表示消费该事件
return true;
}
/**
* 当View中所有的子控件 均被映射成xml后触发
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//小心空指针呀,要是你布局文件里没有两个子View,不就GG了么 注意哈
childView_1 = getChildAt(0);
childView_2 = getChildAt(1);
}
}
到此,我们的ViewDragHelper已经体验了一番,下一章,我们介绍剩下的几个特性,打造我们的侧滑菜单.