一、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
 
 微信扫一扫
微信扫一扫  支付宝扫一扫
支付宝扫一扫 