首先看一下 ViewDragHelper 的介绍
我们知道在自定义 ViewGroup 中经常看到 ViewDragHelper 的身影,官方介绍说它提供了一些有用的操作和状态跟踪,允许用户在其ViewGroup中拖动和重新定位视图。我们来看下使用方法:
- 首先创建 ViewDragHelper
使用 静态方法 create(),ViewDragHelper 构造器对外隐藏,创建方法
/**
* Factory method to create a new ViewDragHelper.
*
* @param forParent Parent view to monitor
* @param sensitivity Multiplier for how sensitive the helper should be about detecting
* the start of a drag. Larger values are more sensitive. 1.0f is normal.
* @param cb Callback to provide information and receive events
* @return a new ViewDragHelper instance
*/
public static ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb) {
final ViewDragHelper helper = create(forParent, cb);
helper.mTouchSlop = (int) (helper.mTouchSlop * (1 / sensitivity));
return helper;
}
forParent 为我们自定义的 ViewGroup 布局, sensitivity 灵敏度,1.0f 为默认值,值越大,越灵敏,Callback 参数最为重要,等下详细介绍。
- 拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
- 处理computeScroll()
@Override
public void computeScroll() {
super.computeScroll();
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
- 处理回调 CallBack
public abstract boolean tryCaptureView(View child, int pointerId);
为必须实现的抽象方法,当我们手指触摸屏幕的时候,ViewDragHelper 将对应的 view 传过来,返回TRUE 说明捕获当前view。
public int clampViewPositionHorizontal(View child, int left, int dx) {
return 0;
}
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
这两个方法主要是对 view 的滑动边际进行控制。
public void onViewReleased(View releasedChild, float xvel, float yvel) {}
当我们取消对view 拖拽控制后,会触发这个方法,如果我们需要view 移到某个位置的时候可以调用 settleCapturedViewAt(int, int)
或者flingCapturedView(int, int, int, int)
方法,因为底层使用的OverScroller
所以我们要在 computeScroll()
中对 continueSettling(boolean)
进行判断是否需要继续滑动。
public void onEdgeDragStarted(int edgeFlags, int pointerId) {}
在需要边缘拖动的地方,对传入的edgeFlags 进行判断即可。