处理RecyclerView滚动与点击事件(如:跑马灯)

在使用 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
mScrollTask = new Runnable() {
@Override
public void run() {
rvWidget.smoothScrollBy(6, 0);
mHandler.postDelayed(this, 30); // 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) {
// 滚动中,且滑动距离小于等于 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 点击事件的效果。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×