Android ViewDragHelper使用方法详解

 更新时间:2017年12月07日 14:57:24   作者:难不难太难了  
这篇文章主要为大家详细介绍了Android ViewDragHelper的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

帮我们实现各种类型的复杂手势操作。其实例通过静态工厂创建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代表动画完成,进去一看就明白了,需要判断滑动事件是否完成,如果完成就不再刷新,如果没完成就刷新。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android SharedPreferences实现记住密码和自动登录

    Android SharedPreferences实现记住密码和自动登录

    这篇文章主要为大家详细介绍了Android SharedPreferences实现记住密码和自动登录,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • Android入门教程之Picasso框架

    Android入门教程之Picasso框架

    本文会先介绍Picasso的基本使用方法,让您快速上手Picasso。后面我们分享实现ListView显示网络图片的实例,从源码角度详细分析它的实现,有需要的可以参考借鉴。
    2016-08-08
  • Android仿微信公众号界面

    Android仿微信公众号界面

    这篇文章主要为大家详细介绍了Android仿微信公众号界面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Android中asset和raw的区别详解

    Android中asset和raw的区别详解

    本文重点给大家介绍android中asset和raw的区别,以及在使用过程中需要注意点,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧
    2016-07-07
  • Android系统服务概览

    Android系统服务概览

    这篇文章介绍了Android系统服务,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • 详解如何在Flutter中用小部件创建响应式布局

    详解如何在Flutter中用小部件创建响应式布局

    由于Flutter的跨平台、单一代码库的能力,了解屏幕管理以防止像柔性溢出错误或糟糕的用户界面设计这样的问题是至关重要的。本文将探讨如何用灵活和扩展的小部件创建响应式布局,需要的可以参考一下
    2022-02-02
  • Android 自动化测试经验分享 深入UiScrollable

    Android 自动化测试经验分享 深入UiScrollable

    UiScrollable是一个UiCollection(这东西还没搞懂),我们可以使用它,在可滑动的页面(水平滑动或上下滑动都可以)上查找我们想要的控件(item)
    2013-05-05
  • Android手势识别功能

    Android手势识别功能

    这篇文章主要为大家详细介绍了Android手势识别功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • Android自定义星星评分控件

    Android自定义星星评分控件

    这篇文章主要为大家详细介绍了Android自定义星星评分控件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • Android路由框架ARouter的使用示例

    Android路由框架ARouter的使用示例

    组件化或者模块化开发模式,已逐渐成为热浪的形式,使用这些模式可以让我们程序更容易的扩展、更方便的维护、更快捷的同步开发与更简单的单独调试,而ARouter的出现就是让组件间、模块间是实现完全的独立。ARouter主要解决组件间、模块间的界面跳转问题。
    2021-06-06

最新评论