Android 滑动手势和项目点击在 RecyclerView 中不能一起工作
Android Swipe gesture and item click both not working together in RecyclerView
我使用 recyclerview 实现了日历。导航到上个月和下个月,根据要求,客户想要滑动功能。
所以我使用以下代码实现了该功能:
recyclerView.setOnTouchListener(new OnSwipeTouchListener(context) {
public void onSwipeTop() {
}
public void onSwipeRight() {
onPreviousMonth();
}
public void onSwipeLeft() {
onNextMonth();
}
public void onSwipeBottom() {
}
});
使用这个 touchListener,它可以完全用于日历的滑动功能。
But after adding this feature, click of the recyclerview item not
working. When I remove touch listener, click of the recyclerview item working
perfectly.
我在代码中遗漏了什么?任何的想法?两者没有一起工作。
这是 OnSwipeTouchListener:
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context ctx) {
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
result = true;
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}
你可以这样添加逻辑,
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
y1 = event.getY();
t1 = System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
x2 = event.getX();
y2 = event.getY();
t2 = System.currentTimeMillis();
if (x1 == x2 && y1 == y2 && (t2 - t1) < DURATION_TO_CONSIDER_CLICK) {
// Consider as normal click or tap
} else if ((t2 - t1) >= DURATION_TO_CONSIDER_CLICK) {
// Consider as long click or tap
} else if (x1 > x2) {
// Consider as left swipe
} else if (x2 > x1) {
// Consider as right swipe
}
return true;
}
return false;
}
请注意,这仅供参考,您可能需要稍微更改以上逻辑才能满足您的期望。
谢谢
您应该确保 TouchListener
没有 消耗 触摸事件。如果您从 onTouch() 方法 return 为真,Android 将认为它已消耗并且不会将其传递给其他各种触摸处理程序(我假设将包括 ClickListener
)。
我会考虑将 ItemTouchHelper 附加到您的 RecyclerView。
实现是这样的:
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
if (direction == ItemTouchHelper.RIGHT) {
onPreviousMonth();
} else if (direction == ItemTouchHelper.LEFT) {
onNextMonth();
}
}
}).attachToRecyclerView(recyclerView);
我使用 recyclerview 实现了日历。导航到上个月和下个月,根据要求,客户想要滑动功能。
所以我使用以下代码实现了该功能:
recyclerView.setOnTouchListener(new OnSwipeTouchListener(context) {
public void onSwipeTop() {
}
public void onSwipeRight() {
onPreviousMonth();
}
public void onSwipeLeft() {
onNextMonth();
}
public void onSwipeBottom() {
}
});
使用这个 touchListener,它可以完全用于日历的滑动功能。
But after adding this feature, click of the recyclerview item not working. When I remove touch listener, click of the recyclerview item working perfectly.
我在代码中遗漏了什么?任何的想法?两者没有一起工作。
这是 OnSwipeTouchListener:
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context ctx) {
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
result = true;
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}
你可以这样添加逻辑,
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
y1 = event.getY();
t1 = System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
x2 = event.getX();
y2 = event.getY();
t2 = System.currentTimeMillis();
if (x1 == x2 && y1 == y2 && (t2 - t1) < DURATION_TO_CONSIDER_CLICK) {
// Consider as normal click or tap
} else if ((t2 - t1) >= DURATION_TO_CONSIDER_CLICK) {
// Consider as long click or tap
} else if (x1 > x2) {
// Consider as left swipe
} else if (x2 > x1) {
// Consider as right swipe
}
return true;
}
return false;
}
请注意,这仅供参考,您可能需要稍微更改以上逻辑才能满足您的期望。 谢谢
您应该确保 TouchListener
没有 消耗 触摸事件。如果您从 onTouch() 方法 return 为真,Android 将认为它已消耗并且不会将其传递给其他各种触摸处理程序(我假设将包括 ClickListener
)。
我会考虑将 ItemTouchHelper 附加到您的 RecyclerView。
实现是这样的:
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
if (direction == ItemTouchHelper.RIGHT) {
onPreviousMonth();
} else if (direction == ItemTouchHelper.LEFT) {
onNextMonth();
}
}
}).attachToRecyclerView(recyclerView);