一、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