首先感谢http://blog.csdn.net/lmj623565791/article/details/46858663hongyang的文章。之前看过ViewDragHelper类也读过一些demo一直都是半知半解且之前一些自己定义的ViewGroup大都不是按这样的方式来写,这一次抓紧一次自己写一个demo熟悉ViewDragHelper。ViewDragHelper存在于v4包种。目的用于帮助我们自己定义ViewGroup。
先上效果图:
第一步,声明ViewDragHelper:
ViewDragHelper.create(this, 1.0f, new ViewDragCallback());
当中1.0f代表最小滑动距离touchSlop是系统默认的多少倍数越大的话越灵敏。
第二步,继承ViewDragHelper.CallBack实现里面的方法来满足滑动需求。
private class ViewDragCallback extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View view, int i) {
return view == mContentView || view == mDeleteView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
Log.w(TAG, "clampViewPositionHorizontal = " + left + "/" + dx);
int realLeft = left;
if (child == mContentView) {
if (left > 0) {// right scroll
realLeft = left > mDeleteView.getWidth() ?
mDeleteView.getWidth() : left;
} else if (left < 0) {// left scroll
realLeft = Math.abs(left) > mDeleteView.getWidth() ?
-mDeleteView.getWidth() : left;
}
}
return realLeft;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
Log.w(TAG, "--- scroll finish when finger up ---");
Log.w(TAG, "onViewReleased = " + xvel + "/" + yvel);
if (releasedChild == mContentView) {
if (xvel > 0) {
mDragHlper.settleCapturedViewAt(point.x, point.y);
} else {
mDragHlper.settleCapturedViewAt(point.x - mDeleteView.getWidth(), point.y);
}
invalidate();
}
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
Log.w(TAG, "--- when view position changed = " + left + "/" + dx);
if (changedView == mContentView) {
mDeleteView.offsetLeftAndRight(dx);
} else if (changedView == mDeleteView) {
mContentView.offsetLeftAndRight(dx);
}
invalidate();
}
}
tryCaptureView:这种方法仅仅有返回true才干进行滑动。否则没有效果。
onViewReleased:这种方法指当手放开后监听当速度满足需求的时候直接滑动到设定的地方。
onViewPositionChanged:当被CaptureView滑动的时候设置DeleteView也移动到相相应的地方。
clampViewPositionHorizontal:设置这个ViewGoup中的ContentView的滑动区域。
第三步,复写手指控制方法:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = MotionEventCompat.getActionMasked(ev);
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
return false;
}
return mDragHlper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHlper.processTouchEvent(event);
return true;
}
关于ViewDragHelper有例如以下几点:
ViewDragHelper.Callback是连接ViewDragHelper与view之间的桥梁(这个view通常是指拥子view的容器即parentView);
ViewDragHelper的实例是通过静态工厂方法创建的;
你能够指定拖动的方向;
ViewDragHelper能够检測到是否触及到边缘;
ViewDragHelper并非直接作用于要被拖动的View,而是使其控制的视图容器中的子View能够被拖动,假设要指定某个子view的行为,须要在Callback中想办法;
ViewDragHelper的本质事实上是分析onInterceptTouchEvent和onTouchEvent的MotionEvent參数,然后依据分析的结果去改变一个容器中被拖动子View的位置( 通过offsetTopAndBottom(int offset)和offsetLeftAndRight(int offset)方法 ),他能在触摸的时候推断当前拖动的是哪个子View;
尽管ViewDragHelper的实例方法 ViewDragHelper create(ViewGroup forParent, Callback cb) 能够指定一个被ViewDragHelper处理拖动事件的对象 ,但ViewDragHelper类的设计决定了其适用于被包括在一个自己定义ViewGroup之中,而不是对随意一个布局上的视图容器使用ViewDragHelper。
源代码地址:
https://github.com/Neacy/HoriazontalDragView