ViewDragHelper的一些研究

最近想了解自定义view的知识,没想到在网上找到了一个仿QQ5.0的,就拿来学习学习。里面涉及到了一个类ViewDragHelper,所以就要好好研究一下它。这个类是在google2013 I/O大会上推出的2个组件中slidingPaneLayout和DrawerLayout就使用到了这个类,那么这个类是干嘛用的呢?从字面意思上面看就是一个View拖拽的帮助类,那我们就来学一下怎么使用它吧。

任何类的使用必须要有它的对象,ViewDragHelper类有一个工厂方法用来创建类的实例,

viewDragHelper = ViewDragHelper.create(this, callback);
viewDragHelper = ViewDragHelper.create(this, 1.0f,callback);
从上面看到,create方法是有2种的,第二种的第二个 参数的意思就是拖拽的灵敏度的高度,1.0f表示是默认的。第一个参数是当前要跟ViewDragHelper链接的ViewGroup,第三个参数就是一个回调方法,我们在对view进行拖拽的时候的操作就是在这个callback里面进行的.当我们实例化了这个类后,就该考虑在哪里将我们的View的touch事件交给ViewdragHelper来实现,我们知道所有viewGroup的touch事件都是从dispatchTouchEvent开始的,那么我们就应该在拦截方法onInterceptTouchEvent中将改事件拦截并在这里将touch事件交给ViewDragHelper同时在onTouchEvent让ViewDragHelper来处理这个事件,代码如下:

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		final int action = MotionEventCompat.getActionMasked(ev);
		if(action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP){
			viewDragHelper.cancel();
			return false;
		}
		return viewDragHelper.shouldInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		viewDragHelper.processTouchEvent(event);
		return true;
	}

至此我们完成了初始化工作,那么接下来我们来看一下上文提到过的callback接口中的方法

public int clampViewPositionHorizontal(View child, int left, int dx) {
			if(mainView.getLeft()+dx < 0){
				return 0;
			}
			return left;
		}
这个方法的意思就是当你水平拖拽view的时候要回调的方法,返回的值就是你的view离屏幕左边的距离,那么我们可以想到垂直方向拖拽也是有其对应的方法,不过ViewDragHelper默认是水平拖拽,如果需要垂直拖拽的话,请提前设置拖拽方式。那么这个方法一般都会和一个方法一起出现

@Override
public int getViewHorizontalDragRange(View child) {
return width;
}

这个方法返回的值是水平滑动的范围,这个值一般在onMeasure中获取,将会在后面作为ViewGroup的位置更新的参数,假如有两个子View的时候我们需要在

 

@Override
		public boolean tryCaptureView(View arg0, int arg1) {
			return true;
		}
这个方法总return true,此时你的2个View都是可以拖拽,如果return false ,那么都不能拖拽。如果你想让某一个可以拖拽,另一个不能拖拽的话,就请return arg0 == YourView。

这样下来,你的ViewGroup是可以拖拽的,但是如果你要动态的更新VIewGroup的位置或者什么的,必须实现另外的两个方法

	@Override
		public void onViewPositionChanged(View changedView, int left, int top,
				int dx, int dy) {
			int mainLeft = mainView.getLeft() + dx;
			if(mainLeft<0){
				mainLeft = 0;
			}else if(mainLeft>width){
				mainLeft = width;
			}
			if(changedView == leftView){
				leftView.layout(0, 0, width, height);
				mainView.layout(mainLeft, 0, mainLeft+width,height);
			}
			dispatchMove(mainLeft);
		}

		@Override
		public void onViewReleased(View releasedChild, float xvel, float yvel) {
			if(xvel>0){
				open(true);
			}else if(xvel < 0){
				close(true);
			}else if(releasedChild == leftView && mainView.getLeft() > width*2/3){
				open(true);
			}else if(releasedChild == mainView && mainView.getLeft() > width/3){
				open(true);
			}else{
				close(true);
			}
		}

第一个方法表示ViewGroup的positionChanged的回调事件,该事件一直伴随这你的拖拽,你可以在这个方法中对ViewGroup的位置,大小什么进行更改,当你完成拖拽后,也就是释放时会调用第二个方法,这个方法一般会处理你手完成拖拽后的ViewGroup的处理。具体来说,onViewReleased是为了当完成拖拽时但是View不在应该在的位置的时候我们对View位置的一种改变,一般会在这个方法里面调用

smoothSlideViewTo(mainView,0, 0);
第一个参数是要移动的View,第二个参数是移动View到距离屏幕左侧的距离,第三个参数就是移动View到距离屏幕顶部的距离。这个方法的作用就是告诉ViewDragHelper,请将这个View移动到指定的位置,当调用这个方法后,ViewdragHelper会回调onViewPositionChanged方法来实现对View位置的自动更新。切记:在调用这个方法的时候记得调用 invalidate()方法,来实现重绘,有时候效果还是没有出来,是因为我们需要再另一个方法中做一些事情

<span style="white-space:pre">	</span>@Override
	public void computeScroll() {
		super.computeScroll();
		if(viewDragHelper.continueSettling(true)){
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

这个方法的写法貌似是固定的,含义我也不太理解,如果有大神理解的话请告诉我,不甚感激!

ViewDragHelper还是很厉害的,我也只知道一点,各位如果有兴趣,请点击下方链接

http://flavienlaurent.com/blog/2013/08/28/each-navigation-drawer-hides-a-viewdraghelper/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值