I have an XML like this (I simplified from the original one, but it still reproduces the issue):
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="@+id/xContainer"
android:clickable="true" // does not help
android:focusable="true" // does not help
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingBottom="8dp"
android:paddingTop="8dp">
<TextView
android:duplicateParentState="true" // does not help
android:clickable="false" // does not help
android:id="@+id/xText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="8dp"
android:text="@string/xText"
android:textSize="14sp" />
</LinearLayout>
</merge>
and it's included from a CardView
like this:
<include layout="@layout/other_stuff_first" />
<include layout="@layout/my_clickable_layout" />
Then I display the item dynamically and attach an OnClickListener
to it, in the same method:
public class XViewHolder extends RecyclerView.ViewHolder {
private final View xContainer;
...
public XViewHolder(@NonNull View itemView) {
xContainer = itemView.findViewById(R.id.xContainer);
}
...
private void bindStuff(RecyclerView.ViewHolder holder, int position) {
if (something) {
xContainer.setVisibility(View.VISIBLE);
xContainer.setOnClickListener(v -> {
// do some stuff
});
} else {
xContainer.setVisibility(View.GONE);
xContainer.setOnClickListener(null);
}
}
}
public class ParentAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
...
((XViewHolder) xViewHolder).bindStuff();
}
}
I put some breakpoints, went through the code in the debugger, and it's properly executed (otherwise it would not show up in the UI at all), so the listener is set.
However, the first time when I click the container, most of the time nothing happens. On the consecutive clicks, it works (90% of time on 2nd click and 100% of time on 3rd+ click). I always click in the same way, the container is big, even if I put my whole finger down with a big force, first click doesn't register.
I found several similar questions, but they're either "all or nothing" (whereas in my case it's just sporadic), or due to some other issues. In my app, there's no work on the main thread after the UI is displayed.
Any ideas what can be wrong?
Edit: after some investigation, the issue only happens if:
my_clickable_layout
is at the bottom of the scrolling container and not initially visible on screen (only becomes visible after the user scrolls down), AND- the user scrolls down fast, AND
- the user taps
my_clickable_layout
within 0-3 seconds after the scroll.
If the layout is immediately visible, OR user scrolls down slowly, OR user taps more than once, then the taps are dispatched properly.
The RecyclerView
itself receives the touch events, because I can always see the logs from the code below, even if I don't see the logs from my children listeners.
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
Timber.w("onInterceptTouchEvent");
return false;
}
});
At this moment I believe this might be a bug in RecyclerView
, which wrongly consumes the first event after a fast scroll - perhaps to detect "end of scrolling" tap?