ViewDragHelper
我们都知道在Google发布的support包中包含了DrawerLayout和SlidingPaneLayout这两个可以滑动的控件,其实这两个布局背后就隐藏着ViewDragHelper。通过ViewDragHelper基本上的滑动需求都可以满足,所以这个方法是各种滑动解决方案的终极绝招
下面我们来进行一个实例,来使用一下ViewDragHelper,类似于QQ的侧滑菜单。废话不多说,上图:
使用ViewDragHelper
- 初始化ViewDragHelper
- 重写拦截、触摸事件交给ViewDragHelper处理
- 处理computeScroll()
- 处理回调接口Callback
初始化ViewDragHelper
ViewDragHelper通常定义在一个ViewGroup的内部,并通过静态工厂方法进行初始化,代码如下:
mHelper = ViewDragHelper.create(this, callback);
对,就这一行代码,这里的this就是只一个ViewGroup了,callback就是刚才我们说的回调接口
重写拦截、触摸事件交给ViewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
mHelper.processTouchEvent(event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mHelper.shouldInterceptTouchEvent(ev);
}
这里就是一个事件拦截和触摸事件监听,上一文中都讲过,这里不在多说,就是调用了DragViewHelper的两个方法而已
处理computeScroll()
因为ViewDragHelper也是通过Scroller来实现平滑移动的,所以我们要重写computeScroll()方法,一般代码如下:
@Override
public void computeScroll() {
if (mHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
处理回调接口Callback
处理回调接口就是最关键的代码了,我们一般需要重写这几个方法
- tryCaptureView
- 这个方法是自动创建的,通过这个方法可以指定哪一个子View可以移动
- clampViewPositionHorizontal
- 这个方法对应的是水平上的滑动
- clampViewPositionVertical
- 这个方法对应的是垂直上的滑动
- 如果想要滑动,这两个方法是必须要重写其中一个或者全部重写的,因为方法默认返回0,即不发生滑动
- onViewReleased
- 这个方法在手指离开屏幕后调用
不多说,直接把代码撸上来,非常简单,对照注释一看就懂,整体代码如下
public class ViewDragHelperDemo extends FrameLayout {
ViewDragHelper mHelper;
View mainView, menuView;
public ViewDragHelperDemo(Context context) {
this(context, null);
}
public ViewDragHelperDemo(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ViewDragHelperDemo(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
/**
* 初始化ViewDragHelper
*/
mHelper = ViewDragHelper.create(this, callback);
}
ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
/**
* 决定滑动的View
*/
return child == mainView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
/**
* 水平方向上的移动
*/
return left;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
/**
* 当手指离开屏幕后,如果当前移动的View和父布局之间的距离小于150,那么则移动回原位
* 如果大于150,那么则滑动到300
*/
if (mainView.getLeft() < 150) {
mHelper.smoothSlideViewTo(mainView, 0, 0);
}else{
mHelper.smoothSlideViewTo(mainView, 300, 0);
}
/**
* 通知重绘
*/
ViewCompat.postInvalidateOnAnimation(DragViewHelperDemo.this);
}
};
/**
* 此方法会在布局加载完毕调用,我们把第一个布局设置为menuView,第二个设置为mainView
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
menuView = getChildAt(0);
mainView = getChildAt(1);
}
/**
* 这里设置触摸/拦截事件给DragViewHelper
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
mHelper.processTouchEvent(event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mHelper.shouldInterceptTouchEvent(ev);
}
/**
* 设置computeScroll
*/
@Override
public void computeScroll() {
if (mHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
运行程序,就会看到和上面一样的效果啦。ViewDragHelper是最麻烦的一种,但是多写一写就好啦~
最后
爱生活,爱小丽,爱Android