Android ViewDragHelper使用方法详解

作者:难不难太难了 时间:2022-08-27 02:01:28 

帮我们实现各种类型的复杂手势操作。其实例通过静态工厂创建ViewDragHelper一般用在一个自定义ViewGroup的内部。

初始化操作


private ViewDragHelper mDrragHelper;
 public SlideViewGroup(@NonNull Context context) {
   this(context,null);
 }

public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
   this(context, attrs,0);
 }

public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {

super(context, attrs, defStyleAttr);
   mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);

}

mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);第一个操作表示当前操作的对象,第二个参数为手势操作敏感度,
第三个参数为我们手势处理的毁掉接口

我们需要先在view事件分发时把手势操作交给ViewFragHelper


@Override
 public boolean onInterceptTouchEvent(MotionEvent event) {
   //交给viewdrag去拦截
   //事件分发拦截
   float x=0;
   int action = event.getAction();
   switch(action){
     case MotionEvent.ACTION_DOWN:
       x =event.getX();
       break;
       // return false;
     case MotionEvent.ACTION_MOVE:
       if (STATE==0&getX()-x<0){
         return mDrragHelper.shouldInterceptTouchEvent(event);
       }else if (STATE==1){
         return mDrragHelper.shouldInterceptTouchEvent(event);
       }
       break;
   }
   return false;
 }
//boolean control=true;//控制downx的初始化
 @Override
 public boolean onTouchEvent(MotionEvent event) {
   mDrragHelper.processTouchEvent(event);
   //if (control)
   float downX=0;
   if (event.getAction()==MotionEvent.ACTION_DOWN){
     downX=event.getRawX();
     if (STATE==1){
       //if (event.getRawX()>0&downX<leftWidth-rightViewWidth)
       //close();
       // Toast.makeText(this.getContext(), "leftWidth"+leftWidth+"rawx"+event.getRawX(), Toast.LENGTH_SHORT).show();
     }

}
   if (event.getAction()==MotionEvent.ACTION_UP){
     //Toast.makeText(this.getContext(), "downx"+downX, Toast.LENGTH_SHORT).show();
     //点击删除//&downX>leftWidth-rightViewWidth&downX<leftWidth-rightViewWidth/2
    // Toast.makeText(this.getContext(), "删除1", Toast.LENGTH_SHORT).show();
     if (STATE==1&event.getRawX()>leftWidth-rightViewWidth&event.getRawX()<leftWidth-rightViewWidth/2){
       // Toast.makeText(this.getContext(), "删除2", Toast.LENGTH_SHORT).show();
       if (skipListener!=null){
        // Toast.makeText(this.getContext(), "删除3", Toast.LENGTH_SHORT).show();
         skipListener.onDelete();
       }
       // Toast.makeText(this.getContext(), "删除", Toast.LENGTH_SHORT).show();
     }
     //点击删除&downX>leftWidth-rightViewWidth/2&downX<leftWidth-rightViewWidth
     if (STATE==1&event.getRawX()>leftWidth-rightViewWidth/2&event.getRawX()<leftWidth){
       // Toast.makeText(this.getContext(), "修改", Toast.LENGTH_SHORT).show();
       if (skipListener!=null){
         skipListener.onDefine();
       }
     }
   }
   return true;
 }

重点在这两句


mDrragHelper.shouldInterceptTouchEvent(event);
mDrragHelper.processTouchEvent(event);

我们可以在onInterceptTouchEvent决定什么时候把事件交给我们的手势操作类
然后是回调类


private ViewDragHelper.Callback mCallback=new ViewDragHelper.Callback() {
   @Override
   public boolean tryCaptureView(View child, int pointerId) {
     return child==leftView;
   }

@Override
   public int clampViewPositionHorizontal(View child, int left, int dx) {
     if (left>=0)
       return 0;
     if (left<-rightViewWidth)
       return -rightViewWidth;

return left;
   }

@Override
   public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
     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
   public void onViewReleased(View releasedChild, float xvel, float yvel) {
     super.onViewReleased(releasedChild, xvel, yvel);
     Log.i("left xvel",xvel+"y"+yvel);
     if (xvel<0){
       open();/* mDrragHelper.smoothSlideViewTo(rightView,rightViewWidth/2,0);*/
     }else if (leftView.getLeft()<-rightViewWidth/2)
     {open();}else {
       // Log.i("left open","open");
       close();
     }
   }

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

@Override
   public void onEdgeTouched(int edgeFlags, int pointerId) {
     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
public void onEdgeTouched(int edgeFlags, int pointerId) {
 super.onEdgeTouched(edgeFlags, pointerId);
 Toast.makeText(getContext(), "edgeTouched", Toast.LENGTH_SHORT).show();
}

如果你想在边缘滑动的时候根据滑动距离移动一个子view,可以通过实现onEdgeDragStarted方法,并在onEdgeDragStarted方法中手动指定要移动的子View


@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
 mDragHelper.captureChildView(mDragView2, pointerId);
}

滑动

手指在当前view的下边缘就可以滑动

下面看一个我在ontochEvent调用的方法


public void open(){
   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
 public void computeScroll() {
   if (mDrragHelper.continueSettling(true)) {
     ViewCompat.postInvalidateOnAnimation(this);
   }
 }

其实滑动本身还是调用的scrollto跟据时间百分比移动,根据比例移动固定距离后就不移动了,所以我们需要重复刷新,需要判断临界条件,可能是时间可能是距离,可以点进continueSetting方法返回false代表动画完成,进去一看就明白了,需要判断滑动事件是否完成,如果完成就不再刷新,如果没完成就刷新。

来源:http://blog.csdn.net/m0_37402140/article/details/77840571

标签:Android,ViewDragHelper
0
投稿

猜你喜欢

  • 详解Android Lint的原理及其使用

    2022-12-23 16:05:47
  • Android 沉浸式状态栏与隐藏导航栏实例详解

    2021-09-08 07:51:14
  • 使用IDEA开发配置Java Web的初始化过程

    2022-09-25 16:33:38
  • springboot 返回json格式数据时间格式配置方式

    2023-12-17 23:27:10
  • Android编程设计模式之抽象工厂模式详解

    2023-07-15 09:35:38
  • java实现Dijkstra最短路径算法

    2022-11-30 21:02:15
  • Eclipse代码格式化设置简单介绍

    2023-10-26 21:59:31
  • Java中初始化List集合的八种方式汇总

    2021-09-20 22:31:54
  • Spring @Bean注解的使用场景与案例实现

    2023-11-20 04:44:22
  • Spring MVC整合 freemarker及使用方法

    2022-06-06 16:41:41
  • SpringBoot任务之详解邮件任务

    2021-08-12 12:49:16
  • C++普通函数指针与成员函数指针实例解析

    2022-09-29 10:19:36
  • 解析使用enumerator模式简化异步操作的详解

    2021-10-08 01:44:54
  • Android测试方法总结

    2022-07-27 08:02:41
  • 详解Java代码常见优化方案

    2023-11-29 03:13:04
  • C#对XML文件的各种操作实现方法

    2023-01-21 06:14:40
  • fastjson转换对象实体@JsonProperty不生效问题及解决

    2023-10-07 00:13:51
  • Java使用Apache.POI中HSSFWorkbook导出到Excel的实现方法

    2022-05-24 17:14:13
  • Android Drawable及其相关类的使用

    2023-10-18 09:32:38
  • Spring注解Autowired的底层实现原理详解

    2022-10-19 11:49:44
  • asp之家 软件编程 m.aspxhome.com