在使用 RecyclerView 进行滚动时,通过定时器实现自动滚动,但在滚动中无法正确触发 item 的点击事件。
因为RecyclerView 滚动与点击事件是独立的,默认情况下,滚动操作可能会影响点击事件的传递。
解决方案
1. 使用 Handler 替代 Timer
在 Android 中,使用 Handler 更适合处理定时任务。替换原有的 Timer 实现,改用 Handler 来处理滚动任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| private Handler mHandler = new Handler(); private Runnable mScrollTask;
mScrollTask = new Runnable() { @Override public void run() { rvWidget.smoothScrollBy(6, 0); mHandler.postDelayed(this, 30); } };
mHandler.postDelayed(mScrollTask, 0);
mHandler.removeCallbacks(mScrollTask);
|
2. 处理点击事件
为了在滚动中也能触发 item 的点击事件,对 RecyclerView 进行自定义处理。使用一个自定义的 RecyclerView 类,通过重写 dispatchTouchEvent 方法,在滚动中模拟点击事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class CustomRecyclerView extends RecyclerView { private boolean isScrolling = false; private float downX;
@Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = ev.getX(); isScrolling = true; break; case MotionEvent.ACTION_MOVE: isScrolling = true; break; case MotionEvent.ACTION_UP: float upX = ev.getX(); float deltaX = Math.abs(upX - downX); if (isScrolling && deltaX <= 30) { View child = findChildViewUnder(ev.getX(), ev.getY()); if (child != null) { int position = getChildAdapterPosition(child); if (position != RecyclerView.NO_POSITION) { getAdapter().onBindViewHolder( (ViewHolder) findViewHolderForAdapterPosition(position), position); performItemClick(child); } } } isScrolling = false; break; } return super.dispatchTouchEvent(ev); }
private void performItemClick(View view) { if (view != null) { view.performClick(); } } }
|
最终通过使用 Handler 处理定时任务和自定义 RecyclerView 处理点击事件,实现了在滚动中仍能正确触发 item 点击事件的效果。