返回介绍

2. 使用方法

发布于 2024-12-23 21:11:39 字数 4079 浏览 0 评论 0 收藏 0

我们这里就以 翔总的这篇文章 中的例子来介绍一下 ViewDragHelper 的使用.另外,本文中的 demo 可以在 这里找到

首先我们创建一个 DragLayout 类并继承自 LinearLayout ,然后我们准备在 DragLayout 放置三个 View 第一个用来被我们拖动然后停止在松手的位置,第二个可以被我们拖动,松手的时候滑动到指定位置,第三个只可以通过触摸边缘来进行拖动,

public class DragLayout extends LinearLayout {

  private ViewDragHelper mDragger;
  private View mDragView;
  private View mAutoBackView;
  private View mEdgeTrackerView;

  private Point mAutoBackOriginPos = new Point();

  public DragLayout(Context context) {
    this(context, null);
  }

  public DragLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initViewDragHelper();
  }

  private void initViewDragHelper() {
    mDragger = ViewDragHelper.create(this,myCallback);
    mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL);
  }

  ViewDragHelper.Callback myCallback = new ViewDragHelper.Callback() {
    @Override
    //child 为当前触摸区域下的 View,如果返回 true,就可以拖拽。
    public boolean tryCaptureView(View child, int pointerId) {
      return child == mDragView || child == mAutoBackView;
    }

    //松手时的回调
    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
      if (releasedChild == mAutoBackView) {
        mDragger.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y);
        invalidate();
      }
    }
    
    //边缘触摸开始时的回调
    @Override
    public void onEdgeDragStarted(int edgeFlags, int pointerId) {
      mDragger.captureChildView(mEdgeTrackerView, pointerId);
    }

    //获取水平方向允许拖拽的区域,这里是父布局的宽-子控件的宽
    @Override
    public int getViewHorizontalDragRange(View child) {
      return getMeasuredWidth() - child.getMeasuredWidth();
    }

    //获取垂直方向允许拖拽的范围
    @Override
    public int getViewVerticalDragRange(View child) {
      return getMeasuredHeight() - child.getMeasuredHeight();
    }

    //left 为 child 即将移动到的水平位置的值,但是返回值会最终决定移动到的值
    //这里直接返回了 left
    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
      return left;
    }
    //同上只是这里是垂直方向
    @Override
    public int clampViewPositionVertical(View child, int top, int dy) {
      return top;
    }
  };

  @Override
  public void computeScroll() {
    if (mDragger.continueSettling(true)) {
      invalidate();
    }
  }

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    return mDragger.shouldInterceptTouchEvent(ev);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    mDragger.processTouchEvent(event);
    return true;
  }

  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    mDragView = getChildAt(0);
    mAutoBackView = getChildAt(1);
    mEdgeTrackerView = getChildAt(2);
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    mAutoBackOriginPos.x = mAutoBackView.getLeft();
    mAutoBackOriginPos.y = mAutoBackView.getTop();
  }
}
  1. 我们首先在构造方法里传入了当前类的对象和我们定义的 ViewDragHelper.Callback 对象初始化了我们的 ViewDragHelper ,然后我们希望所有的边缘触摸都能触发 mEdgeTrackerView 的拖动,所以我们紧接着调用了 mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL); 方法。
  2. 在我们定义的 Callback 中,有多个回调方法,每个回调方法都有它的作用,在代码里注释比较清楚了,我们下面也会解析每一个 Callback 中回调方法的作用。
  3. 第三步我们需要在 onInterceptTouchEvent() 方法和 onTouchEvent() 将事件委托给 ViewDragHelper 去处理,这样 ViewDragHelper 才能根据响应的事件并回调我们自己编写的 Callback 接口来进行响应的处理,
  4. 由于 ViewDragHelper 中的滑动是交给 Srcoller 类来处理的所以这里我们要重写 computeScroll() 方法,配合 Scroller 完成滚动动画。
  5. 最后在 onFinishInflate() 里获取到我们的 View 对象即可。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文