ViewDragHelper

ViewDragHelper

一、概述
       在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是一件很不容易的事,需要自己去处理:多手指的处理、加速度检测等等。 
好在官方在v4的支持包中提供了ViewDragHelper这样一个类来帮助我们方便的编写自定义ViewGroup。简单看一下它的注释:
ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number  of useful operations and state tracking for allowing a user to drag and reposition  views within their parent ViewGroup.

二、ViewDragHelper使用遵循3个步骤:
1、创建实例
   ViewDragHelper helper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback(){ });
创建实例需要3个参数:
第一个就是当前的ViewGroup,
第二个sensitivity,主要用于设置touchSlop: 
helper.mTouchSlop = (int) (helper.mTouchSlop * (1 / sensitivity));  可见传入越大,mTouchSlop的值就会越小。
第三个参数就是Callback,在用户的触摸过程中会回调相关方法,后面会细说。

2、触摸相关方法
   
   
  1. @Override
  2.     public boolean onInterceptTouchEvent(MotionEvent event) //触摸拦截事件
  3.     {
  4.         return helper.shouldInterceptTouchEvent(event);
  5.     }
  6.     @Override
  7.     public boolean onTouchEvent(MotionEvent event) //触摸处理事件
  8.     {
  9.         helper.processTouchEvent(event);
  10.         return true;
  11.     }
   onInterceptTouchEvent中通过使用helper.shouldInterceptTouchEvent(event)来决定我们是否应该拦截当前的事件。
   onTouchEvent中通过helper.processTouchEvent(event)处理事件。

3、实现ViewDragHelper.CallCack相关方法
    
    
  1. new ViewDragHelper.Callback(){
  2.             @Override
  3.             public boolean tryCaptureView(View child, int pointerId)    //view是否可以被拖动
  4.             {
  5.                 return true;
  6.             }
  7.             @Override
  8.             public int clampViewPositionHorizontal(View child, int left, int dx) // 控制水平方向的拖动
  9.             {
  10.                 return left;
  11.             }
  12.             @Override
  13.             public int clampViewPositionVertical(View child, int top, int dy)    // 控制垂直方向的拖动
  14.             {
  15.                 return top;
  16.             }
  17.            @Override public boolean tryCaptureView(View child, int pointerId) { //mEdgeTrackerView禁止直接移动 return child == mDragView || child == mAutoBackView; } //手指释放的时候回调 @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { //mAutoBackView手指释放时可以自动回去 if (releasedChild == mAutoBackView) { mDragger.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y); invalidate(); } } //在边界拖动时回调 @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { mDragger.captureChildView(mEdgeTrackerView, pointerId); } }); mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); }
  18.         }
  19.        
     ViewDragHelper中拦截和处理事件时,需要会回调CallBack中的很多方法来决定一些事,比如:哪些子View可以移动、对某个移动的View的边界的控制等等。
viewDragHelper中复写的方法:
1、tryCaptureView如何返回ture则表示可以捕获该view,你可以根据传入的第一个view参数决定哪些可以捕获
2、clampViewPositionHorizontal,clampViewPositionVertical可以在该方法中对child移动的边界进行控制,left , top 分别为即将移动到的位置,比如横向的情况下,我希望只在ViewGroup的内部移动,即:最小>=paddingleft,最大<=ViewGroup.getWidth()-paddingright-child.getWidth。就可以按照如下代码编写:
    
    
  1.  @Override
  2.             public int clampViewPositionHorizontal(View child, int left, int dx){
  3.                 final int leftBound = getPaddingLeft();
  4.                 final int rightBound = getWidth() - mDragView.getWidth() - leftBound;
  5.                 final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
  6.                 return newLeft;
  7.             }
3、onViewDragStateChanged 
       当ViewDragHelper状态发生变化时回调(IDLE,DRAGGING,SETTING[自动滚动时])
4、onViewPositionChanged
       当captureview的位置发生改变时回调
5、onViewCaptured
       当captureview被捕获时回调
6、onViewReleased 已用
7、onEdgeTouched
       当触摸到边界时回调。
8、onEdgeLock
       true的时候会锁住当前的边界,false则unLock。
9、onEdgeDragStarted 
10、getOrderedChildIndex 
       改变同一个坐标(x,y)去寻找captureView位置的方法。(具体在:findTopChildUnder方法中)

方法的大致的回调顺序:
    
    
  1. shouldInterceptTouchEvent
  2. DOWN:
  3.     getOrderedChildIndex(findTopChildUnder)
  4.     ->onEdgeTouched
  5. MOVE:
  6.     getOrderedChildIndex(findTopChildUnder)
  7.     ->getViewHorizontalDragRange & 
  8.       getViewVerticalDragRange(checkTouchSlop)(MOVE中可能不止一次)
  9.     ->clampViewPositionHorizontal&
  10.       clampViewPositionVertical
  11.     ->onEdgeDragStarted
  12.     ->tryCaptureView
  13.     ->onViewCaptured
  14.     ->onViewDragStateChanged
  15. processTouchEvent:
  16. DOWN:
  17.     getOrderedChildIndex(findTopChildUnder)
  18.     ->tryCaptureView
  19.     ->onViewCaptured
  20.     ->onViewDragStateChanged
  21.     ->onEdgeTouched
  22. MOVE:
  23.     ->STATE==DRAGGING:dragTo
  24.     ->STATE!=DRAGGING:
  25.         onEdgeDragStarted
  26.         ->getOrderedChildIndex(findTopChildUnder)
  27.         ->getViewHorizontalDragRange&
  28.           getViewVerticalDragRange(checkTouchSlop)
  29.         ->tryCaptureView
  30.         ->onViewCaptured
  31.         ->onViewDragStateChanged

ViewDragHelper还能做以下的一些操作:
边界检测、加速度检测(eg:DrawerLayout边界触发拉出)
回调Drag Release(eg:DrawerLayout部分,手指抬起,自动展开/收缩)
移动到某个指定的位置(eg:点击Button,展开/关闭Drawerlayout)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值