介绍
ViewDragHelper是对滑动事件的封装类。他用于ViewGroup中。
之前我们自定义滑动的View自己来实现dispatchTouchEvent会比较复杂,例如,我们自己实现一个SlidingMenu,需要定义一个ViewGroup,然后在onTouchEvent、onInterceptTouchEvent做很多复杂的判断。写起来效率也比较低。
通过ViewDragHelper,可以大大提高完成一个滑动效果的效率。
使用
1. 实例化。
mViewDragHelper = ViewDragHelper.create(this, 1.0f, callback());
参数一,表示要监听滑动事件的ViewGroup对象。
参数二,表示灵敏度。1.0f正常灵敏度
参数三,回调,这个参数比较重要。其中的实现决定了我们对滑动事件的处理。
callBack的回调的意义
new ViewDragHelper.Callback() {
/**
* 判断哪个View可以拖拽
* @param child
* @param pointerId
* @return
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
Log.i("tag", "start tryCapture");
return child == mHeadView;
}
/**
* 返回值,拖拽View移动的距离,左边距
* @param child
* @param left
* @param dx
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
int newLeft = left;
if (left < getPaddingLeft()) {
newLeft = getPaddingLeft();
} else if (left > getMeasuredWidth() - child.getMeasuredWidth()) {
newLeft = getMeasuredWidth() - child.getMeasuredWidth();
}
return newLeft;
}
/**
* 返回值,拖拽View移动的距离,上边距
* @param child
* @param top
* @param dy
* @return
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
if (child == mSecView) {
return child.getTop();
}
int newTop = top;
if (top < getPaddingTop()) {
newTop = getPaddingTop();
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
newTop = getMeasuredHeight() - child.getMeasuredHeight();
}
return newTop;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (releasedChild == mSecView) {
Log.i("tag", "released xvel=" + xvel + ", yvel=" + yvel+", left="+releasedChild.getLeft() +", scroll="+releasedChild.getScrollX());
if (releasedChild.getLeft() > getMeasuredWidth() / 2 || xvel > 0) {
mViewDragHelper.settleCapturedViewAt(getMeasuredWidth() - releasedChild.getMeasuredWidth(), releasedChild.getTop());
invalidate();
} else {
mViewDragHelper.settleCapturedViewAt(0, releasedChild.getTop());
invalidate();
}
}
}
/**
* 当边沿触控到时回调
* @param edgeFlags
* @param pointerId
*/
@Override
public void onEdgeTouched(int edgeFlags, int pointerId) {
super.onEdgeTouched(edgeFlags, pointerId);
Log.i("tag", "edgeTouched edgeFlags=" + edgeFlags + ", pointerId=" + pointerId);
//对mSecView进行滑动捕获,可以绕过tryCaptureView
mViewDragHelper.captureChildView(mSecView, pointerId);
}
/**
* 当在边沿拖拽时回调
* @param edgeFlags
* @param pointerId
*/
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
super.onEdgeDragStarted(edgeFlags, pointerId);
Log.i("tag", "edgeTouched edgeFlags=" + edgeFlags + ", pointerId=" + pointerId);
//对mSecView进行滑动捕获,可以绕过tryCaptureView
mViewDragHelper.captureChildView(mSecView, pointerId);
}
/**
* 如果viewGroup有获取焦点的控件(例如button,editText)等,如果想滑动,此处不能返回0
* @param child
* @return
*/
@Override
public int getViewHorizontalDragRange(View child) {
return super.getViewHorizontalDragRange(child);
}
});
2. 将事件传递给ViewDragHelper处理。
ViewDragHelper定义好了以后,我们要把需要处理的触摸事件传递给他。
/**
* onInterceptTouchEvent应该有viewDragHelper来控制
*
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
/**
* onTouchEvent应该有viewDragHelper控制
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
至此,通过ViewDragHeler已能实现拖动。
ViewDragHelper常用方法解释
//对mSecView进行滑动捕获,可以绕过tryCaptureView.将滑动事件传递给mSecView
mViewDragHelper.captureChildView(mSecView, pointerId);
//让View滑动到指定的位置,常配合 invalidate,computeScroll,mDragHelper.continueSettling使用
mViewDragHelper.settleCapturedViewAt(getMeasuredWidth() - releasedChild.getMeasuredWidth(), releasedChild.getTop());
//是否持续滚动
mDragHelper.continueSettling(true);
参考