Android ViewDragHelper使用方法详解
帮我们实现各种类型的复杂手势操作。其实例通过静态工厂创建ViewDragHelper一般用在一个自定义ViewGroup的内部。
初始化操作
privateViewDragHelpermDrragHelper;
publicSlideViewGroup(@NonNullContextcontext){
this(context,null);
}
publicSlideViewGroup(@NonNullContextcontext,@NullableAttributeSetattrs){
this(context,attrs,0);
}
publicSlideViewGroup(@NonNullContextcontext,@NullableAttributeSetattrs,@AttrResintdefStyleAttr){
super(context,attrs,defStyleAttr);
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);
}
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);第一个操作表示当前操作的对象,第二个参数为手势操作敏感度,
第三个参数为我们手势处理的毁掉接口
我们需要先在view事件分发时把手势操作交给ViewFragHelper
@Override
publicbooleanonInterceptTouchEvent(MotionEventevent){
//交给viewdrag去拦截
//事件分发拦截
floatx=0;
intaction=event.getAction();
switch(action){
caseMotionEvent.ACTION_DOWN:
x=event.getX();
break;
//returnfalse;
caseMotionEvent.ACTION_MOVE:
if(STATE==0&getX()-x<0){
returnmDrragHelper.shouldInterceptTouchEvent(event);
}elseif(STATE==1){
returnmDrragHelper.shouldInterceptTouchEvent(event);
}
break;
}
returnfalse;
}
//booleancontrol=true;//控制downx的初始化
@Override
publicbooleanonTouchEvent(MotionEventevent){
mDrragHelper.processTouchEvent(event);
//if(control)
floatdownX=0;
if(event.getAction()==MotionEvent.ACTION_DOWN){
downX=event.getRawX();
if(STATE==1){
//if(event.getRawX()>0&downXleftWidth-rightViewWidth&downXleftWidth-rightViewWidth&event.getRawX()leftWidth-rightViewWidth/2&downXleftWidth-rightViewWidth/2&event.getRawX()
重点在这两句
mDrragHelper.shouldInterceptTouchEvent(event);
mDrragHelper.processTouchEvent(event);
我们可以在onInterceptTouchEvent决定什么时候把事件交给我们的手势操作类
然后是回调类
privateViewDragHelper.CallbackmCallback=newViewDragHelper.Callback(){
@Override
publicbooleantryCaptureView(Viewchild,intpointerId){
returnchild==leftView;
}
@Override
publicintclampViewPositionHorizontal(Viewchild,intleft,intdx){
if(left>=0)
return0;
if(left<-rightViewWidth)
return-rightViewWidth;
returnleft;
}
@Override
publicvoidonViewPositionChanged(ViewchangedView,intleft,inttop,intdx,intdy){
super.onViewPositionChanged(changedView,left,top,dx,dy);
rightView.layout(leftWidth+left,0,leftWidth+rightViewWidth,viewHeight);
/*if(left<0&left>rightViewWidth/2){
mDrragHelper.smoothSlideViewTo(leftView,left,0);
mDrragHelper.smoothSlideViewTo(rightView,left,0);
}*/
/*if(left>=-(leftWidth+rightViewWidth)){
rightView.layout(leftWidth+left,0,leftWidth+rightViewWidth,viewHeight);
}
if(left<-(leftWidth+rightViewWidth)){
rightView.layout(leftWidth,0,leftWidth+rightViewWidth,viewHeight);
}*/
}
@Override
publicvoidonViewReleased(ViewreleasedChild,floatxvel,floatyvel){
super.onViewReleased(releasedChild,xvel,yvel);
Log.i("leftxvel",xvel+"y"+yvel);
if(xvel<0){
open();/*mDrragHelper.smoothSlideViewTo(rightView,rightViewWidth/2,0);*/
}elseif(leftView.getLeft()<-rightViewWidth/2)
{open();}else{
//Log.i("leftopen","open");
close();
}
}
@Override
publicintgetViewHorizontalDragRange(Viewchild){
return-rightViewWidth;
}
@Override
publicvoidonEdgeTouched(intedgeFlags,intpointerId){
super.onEdgeTouched(edgeFlags,pointerId);
}
};
tryCaptureView的返回值表示我们允许操作的child
clampViewPositionHorizontal()方法的默认返回值为0,返回值代表水平移动的距离,也就是left值,当返回left值时,我们操作的view就会跟着我们的拖动而移动,当然还有数值方向的方法,如果需要也可以重写竖直操作的方法
onViewPositionChanged()方法就是当我们移动时就会回调这个方法,此处的left参数就是水平移动返回的left,dx就是水平距离相对变化
onViewRelased()方法就是手指抬起时(释放)时回调的方法,xvel每秒钟水平速度速度慢时为0,单位为像素,yvel为每秒钟竖直方向的速度。速度有正负之分
滑动边缘:
分为滑动左边缘还是右边缘:EDGE_LEFT和EDGE_RIGHT,下面的代码设置了可以处理滑动左边缘:
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
假如如上设置,onEdgeTouched方法会在左边缘滑动的时候被调用,这种情况下一般都是没有和子view接触的情况。
@Override
publicvoidonEdgeTouched(intedgeFlags,intpointerId){
super.onEdgeTouched(edgeFlags,pointerId);
Toast.makeText(getContext(),"edgeTouched",Toast.LENGTH_SHORT).show();
}
如果你想在边缘滑动的时候根据滑动距离移动一个子view,可以通过实现onEdgeDragStarted方法,并在onEdgeDragStarted方法中手动指定要移动的子View
@Override
publicvoidonEdgeDragStarted(intedgeFlags,intpointerId){
mDragHelper.captureChildView(mDragView2,pointerId);
}
滑动
手指在当前view的下边缘就可以滑动
下面看一个我在ontochEvent调用的方法
publicvoidopen(){
if(listener!=null){
listener.onOpen(this);
}
if(mDrragHelper.smoothSlideViewTo(leftView,-rightViewWidth,0))
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this);
STATE=1;
}
就是平滑滑动,
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this)
上面那个方法就是刷新布局(重绘操作)
然后会回调次viewgroup的computerScroll
@Override
publicvoidcomputeScroll(){
if(mDrragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
其实滑动本身还是调用的scrollto跟据时间百分比移动,根据比例移动固定距离后就不移动了,所以我们需要重复刷新,需要判断临界条件,可能是时间可能是距离,可以点进continueSetting方法返回false代表动画完成,进去一看就明白了,需要判断滑动事件是否完成,如果完成就不再刷新,如果没完成就刷新。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。