如何在 ItemTouchHelpers 中的某个点停止滑动?
How to stop swipe at some point in ItemTouchHelpers?
我需要在开始时滑动某个项目,或者完全滑动,或者在当前点停止。就像在 Yandex 邮件中一样。我想做 setLeft(dx)
和 setRight(dx)
但这不是我需要的
我有 class
ItemTouchHelperCallback extends ItemTouchHelper.Callback
在里面我覆盖了方法
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View itemView = viewHolder.itemView;
// not sure why, but this method get's called for viewholder that are already swiped away
if (viewHolder.getAdapterPosition() == -1) {
// not interested in those
return;
}
float height = (float) itemView.getBottom() - (float) itemView.getTop();
float width = height / 3;
float temdX=0;
Bitmap icon;
if(dX > 0 || lastdX>0){
//try stop item while back in dx=0, but workin only while i debug
if(lastdX>=100 && dX==0 &&lastdX!=0 &&lastdX!=-720)
{
dX=100;
isCurrentlyActive=true;
}
lastdX=dX;
itemView.setLeft((int) dX);
p.setColor(Color.GREEN);
RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_y);
RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width, (float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width);
c.drawBitmap(icon, null, icon_dest, p);
} else if(lastdX<0 || dX<0) {
if(lastdX<=-100 && dX==0 &&lastdX!=0 &&lastdX!=720)
{
dX=-100;
//itemView.setTranslationX(-200);
isCurrentlyActive=true;
}
lastdX=dX;
itemView.setRight((int)(dX));
p.setColor(Color.RED);
RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_x);
RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width, (float) itemView.getRight() - width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
我需要做类似的事情,一开始我也想使用 ItemTouchHelper 中提供的回调。事实证明这不是正确的方法。
如果您想在滑动过程中停止(或通常控制)视图的平移,您需要能够修改并保存位移 dX 的值。如果您使用 ItemTouchHelper,则此值在可用回调之外进行控制。
我的解决方案是使用自定义的 touchListener 实现滑动,附加在回收器视图的视图持有者中。您可以找到基本实现的示例 here。如果您需要考虑对项目的点击,请记住您还需要在 touchListener 中实现它。
希望对您有所帮助。
编辑
这里是自定义 ItemTouchListener 的片段。侦听器已简化,仅显示代码以在滑动期间处理视图上的翻译。为了停止滑动,只需在 ACTION_MOVE.
下对 translationX 执行限制逻辑即可
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
public class ItemTouchListener implements View.OnTouchListener {
private int mSlop;
private View mView;
private float mDownX, mDownY;
private boolean mSwiping;
private int mSwipingSlop;
private VelocityTracker mVelocityTracker;
private float mTranslationX;
public ItemTouchListener(View view) {
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
mSlop = vc.getScaledTouchSlop();
mView = view;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// offset because the view is translated during swipe
motionEvent.offsetLocation(mTranslationX, 0);
switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
mDownX = motionEvent.getRawX();
mDownY = motionEvent.getRawY();
return true;
}
case MotionEvent.ACTION_UP: {
// if needed, implement part of limit swipe logic also here
if (mVelocityTracker == null) {
break;
}
mVelocityTracker.addMovement(motionEvent);
mVelocityTracker.computeCurrentVelocity(1000);
mVelocityTracker.recycle();
mVelocityTracker = null;
mTranslationX = 0;
mDownX = 0;
mDownY = 0;
mSwiping = false;
break;
}
case MotionEvent.ACTION_CANCEL: {
if (mVelocityTracker == null) {
break;
}
mVelocityTracker.recycle();
mVelocityTracker = null;
mTranslationX = 0;
mDownX = 0;
mDownY = 0;
mSwiping = false;
break;
}
case MotionEvent.ACTION_MOVE: {
if (mVelocityTracker == null) {
break;
}
mVelocityTracker.addMovement(motionEvent);
float deltaX = motionEvent.getRawX() - mDownX;
float deltaY = motionEvent.getRawY() - mDownY;
if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
mSwiping = true;
mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop);
// cancel view's touch
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
(motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
cancelEvent.recycle();
}
if (mSwiping) {
// limit deltaX here: this will keep the swipe up to desired point
mTranslationX = deltaX;
mView.setTranslationX(deltaX - mSwipingSlop);
return true;
}
break;
}
}
return false;
}
}
我需要在开始时滑动某个项目,或者完全滑动,或者在当前点停止。就像在 Yandex 邮件中一样。我想做 setLeft(dx)
和 setRight(dx)
但这不是我需要的
我有 class
ItemTouchHelperCallback extends ItemTouchHelper.Callback
在里面我覆盖了方法
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View itemView = viewHolder.itemView;
// not sure why, but this method get's called for viewholder that are already swiped away
if (viewHolder.getAdapterPosition() == -1) {
// not interested in those
return;
}
float height = (float) itemView.getBottom() - (float) itemView.getTop();
float width = height / 3;
float temdX=0;
Bitmap icon;
if(dX > 0 || lastdX>0){
//try stop item while back in dx=0, but workin only while i debug
if(lastdX>=100 && dX==0 &&lastdX!=0 &&lastdX!=-720)
{
dX=100;
isCurrentlyActive=true;
}
lastdX=dX;
itemView.setLeft((int) dX);
p.setColor(Color.GREEN);
RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_y);
RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width, (float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width);
c.drawBitmap(icon, null, icon_dest, p);
} else if(lastdX<0 || dX<0) {
if(lastdX<=-100 && dX==0 &&lastdX!=0 &&lastdX!=720)
{
dX=-100;
//itemView.setTranslationX(-200);
isCurrentlyActive=true;
}
lastdX=dX;
itemView.setRight((int)(dX));
p.setColor(Color.RED);
RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_x);
RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width, (float) itemView.getRight() - width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
我需要做类似的事情,一开始我也想使用 ItemTouchHelper 中提供的回调。事实证明这不是正确的方法。
如果您想在滑动过程中停止(或通常控制)视图的平移,您需要能够修改并保存位移 dX 的值。如果您使用 ItemTouchHelper,则此值在可用回调之外进行控制。
我的解决方案是使用自定义的 touchListener 实现滑动,附加在回收器视图的视图持有者中。您可以找到基本实现的示例 here。如果您需要考虑对项目的点击,请记住您还需要在 touchListener 中实现它。
希望对您有所帮助。
编辑 这里是自定义 ItemTouchListener 的片段。侦听器已简化,仅显示代码以在滑动期间处理视图上的翻译。为了停止滑动,只需在 ACTION_MOVE.
下对 translationX 执行限制逻辑即可import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
public class ItemTouchListener implements View.OnTouchListener {
private int mSlop;
private View mView;
private float mDownX, mDownY;
private boolean mSwiping;
private int mSwipingSlop;
private VelocityTracker mVelocityTracker;
private float mTranslationX;
public ItemTouchListener(View view) {
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
mSlop = vc.getScaledTouchSlop();
mView = view;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// offset because the view is translated during swipe
motionEvent.offsetLocation(mTranslationX, 0);
switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
mDownX = motionEvent.getRawX();
mDownY = motionEvent.getRawY();
return true;
}
case MotionEvent.ACTION_UP: {
// if needed, implement part of limit swipe logic also here
if (mVelocityTracker == null) {
break;
}
mVelocityTracker.addMovement(motionEvent);
mVelocityTracker.computeCurrentVelocity(1000);
mVelocityTracker.recycle();
mVelocityTracker = null;
mTranslationX = 0;
mDownX = 0;
mDownY = 0;
mSwiping = false;
break;
}
case MotionEvent.ACTION_CANCEL: {
if (mVelocityTracker == null) {
break;
}
mVelocityTracker.recycle();
mVelocityTracker = null;
mTranslationX = 0;
mDownX = 0;
mDownY = 0;
mSwiping = false;
break;
}
case MotionEvent.ACTION_MOVE: {
if (mVelocityTracker == null) {
break;
}
mVelocityTracker.addMovement(motionEvent);
float deltaX = motionEvent.getRawX() - mDownX;
float deltaY = motionEvent.getRawY() - mDownY;
if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
mSwiping = true;
mSwipingSlop = (deltaX > 0 ? mSlop : -mSlop);
// cancel view's touch
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
(motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
cancelEvent.recycle();
}
if (mSwiping) {
// limit deltaX here: this will keep the swipe up to desired point
mTranslationX = deltaX;
mView.setTranslationX(deltaX - mSwipingSlop);
return true;
}
break;
}
}
return false;
}
}