ViewDragHelper详解

一、ViewDragHelper透传

ViewDragHelper是android官方提供的一个用于拖拽控件的类。在很多场合下,我们需要在一个控件上拖动进行一些交互操作,而ViewDragHelper的出现就使这个过程变得更加简单。此外,ViewDragHelper还提供了一些透传的操作,这意味着你可以在ViewDragHelper的回调函数中操作它所依赖的控件,并不需要对控件进行额外的监听和操作,大大提升了代码编写效率。

示例代码:

public class DragView extends FrameLayout {

    private ViewDragHelper mViewDragHelper;

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return false;
            }

            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                // 透传操作,在View位置改变的时候同步改变背景颜色
                setBackground(Color.RED);
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }

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

二、ViewDragHelper Scroll/边界控制

ViewDragHelper还可以控制控件的滑动范围以及边界。在回调函数的onEdgeDragStarted方法中,可以获取到触摸边界的距离以及边界的方向,在此基础上可以定义一些边缘控制操作。

示例代码:

ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
    // ...

    @Override
    public void onEdgeDragStarted(int edgeFlags, int pointerId) {
        super.onEdgeDragStarted(edgeFlags, pointerId);
        // 边界控制,在边界处开始滑动时设置TargetView的位置以及滑动范围
        mViewDragHelper.captureChildView(mTargetView, pointerId);
        mViewDragHelper.settleCapturedViewAt(0, 0);
        invalidate();
    }

    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
        // 控制水平方向的滑动范围
        final int leftBound = getPaddingLeft();
        final int rightBound = getWidth() - child.getWidth() - getPaddingRight();
        final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
        return newLeft;
    }

    @Override
    public int clampViewPositionVertical(View child, int top, int dy) {
        // 控制竖直方向的滑动范围
        final int topBound = getPaddingTop();
        final int bottomBound = getHeight() - child.getHeight() - getPaddingBottom();
        final int newTop = Math.min(Math.max(top, topBound), bottomBound);
        return newTop;
    }

    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
        // 滑动结束后的回调,可以在这里进行一些结束操作
    }
});

三、ViewDragHelper使用

在使用ViewDragHelper时,需要将其绑定到要拖拽的控件上,同时在控件的手势事件监听中透传ViewDragHelper的事件,从而达到拖拽控件的目的。

示例代码:

public class DragView extends FrameLayout {

    private ViewDragHelper mViewDragHelper;

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return child.getId() == R.id.target;
            }

            @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 boolean onInterceptTouchEvent(MotionEvent event) {
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }

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

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

四、ViewDragHelper透传事件

在使用ViewDragHelper时,可以透传一些事件,比如点击事件、长按事件、焦点事件等,从而使拖拽控件的交互更加丰富。

示例代码:

ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
    // ...

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
        child.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mViewDragHelper.isDragging();
            }
        });

        child.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getContext(), "click", Toast.LENGTH_SHORT).show();
            }
        });

        child.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(getContext(), "long click", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
        return true;
    }
});

五、ViewDragHelper类

ViewDragHelper是一个辅助类,提供了一些拖拽控件的基本操作和回调函数,这些函数和方法包括:

  • create()方法:创建一个ViewDragHelper实例
  • xVelocity和yVelocity:设置或获取x轴和y轴方向的速度值
  • shouldInterceptTouchEvent()方法:判断是否需要在ViewGroup的onInterceptTouchEvent()方法中拦截触摸事件
  • processTouchEvent()方法:处理触摸事件
  • settleCapturedViewAt()方法:设置TargetView滑动到指定位置
  • continueSettling()方法:持续动画滑动
  • callback属性:ViewDragHelper.Callback回调函数

六、ViewDragHelper右滑

在ViewDragHelper中,可以通过onTouchEvent()方法判断是否拖动了控件,并根据拖动的方向进行相应操作。例如在右滑时,可以将TargetView向右滑动一个固定的距离。

示例代码:

public boolean onTouchEvent(MotionEvent event) {
    mViewDragHelper.processTouchEvent(event);
    if (event.getAction() == MotionEvent.ACTION_UP) {
        if (getChildAt(0).getLeft() < getWidth() / 2) {
            mViewDragHelper.settleCapturedViewAt(0, 0);
        } else {
            mViewDragHelper.settleCapturedViewAt(getWidth() - getChildAt(0).getWidth(), 0);
        }
        invalidate();
    }
    return true;
}

七、ViewDragHelper阿拉伯语

在ViewDragHelper使用场景中,可能会出现阿拉伯语的情况,此时可以调用ViewDragHelper的setLayoutDirection()方法,将布局方向设为RTL(Right-to-Left),从而保证阿拉伯语的正确显示。

示例代码:

ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
    // ...

    @Override
    public void onEdgeDragStarted(int edgeFlags, int pointerId) {
        super.onEdgeDragStarted(edgeFlags, pointerId);
        setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
        mViewDragHelper.captureChildView(mTargetView, pointerId);
        mViewDragHelper.settleCapturedViewAt(getMeasuredWidth() - mTargetView.getMeasuredWidth(), 0);
        invalidate();
    }
});

八、ViewDragHelper刷新后位置回到

有时候,ViewDragHelper在处理完触摸事件后会将控件位置恢复到初始位置,此时需要通过在onLayout()方法中计算控件位置,将控件重新放置到目标位置。

示例代码:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    int childLeft = getPaddingLeft();
    int childTop = getPaddingTop();

    mTargetView.layout(childLeft, childTop, childLeft + mTargetView.getMeasuredWidth(),
            childTop + mTargetView.getMeasuredHeight());
}

九、ViewDragHelper RecyclerView选取

ViewDragHelper在RecyclerView中的使用,可以实现RecyclerView中指定Item的拖拽效果,从而提高用户交互效果。

示例代码:

public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private final ItemTouchHelperAdapter mAdapter;

    public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
        mAdapter = adapter;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    }
}

在RecyclerView中使用ViewDragHelper需要通过调用ItemTouchHelper的attachToRecyclerView()方法,将ItemTouchHelper和RecyclerView绑定起来,在此基础上可以实现RecyclerViewItem的拖拽效果。

示例代码:

ItemTouchHelper.Callback callback = new ItemTouchHelperCallback(mAdapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(mRecyclerView);

以上就是ViewDragHelper的详细介绍,对于想要实现一些拖拽效果的开发者来说,ViewDragHelper绝对是一个非常好用的工具。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/243796.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 12:58
下一篇 2024-12-12 12:58

相关推荐

  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25
  • C语言贪吃蛇详解

    一、数据结构和算法 C语言贪吃蛇主要运用了以下数据结构和算法: 1. 链表 typedef struct body { int x; int y; struct body *nex…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25

发表回复

登录后才能评论