8

This is driving me crazy. Something that is implemented by default in ListView is missing from RecyclerView.

I want to have the exact behavior of a listview which is set to single choice mode. I tried the solution from this question but it doesn't fully solve the problem. When I touch the list with 2-3 fingers etc it may only highlight one row indeed, but if I lift my fingers rapidly everything gets triggered even tho only one row is highlighted each time. (I can also hear the sound effect from my phone that gets repeated 3 times very fast)

Basically I want to disable multi touch events from the phone so that the list is forced to select only 1 item each time no matter how many fingers the user uses

Community
  • 1
  • 1
ThanosFisherman
  • 5,626
  • 12
  • 38
  • 63
  • I cannot reproduce your problem on a Nexus 5 with the code as we discussed in that question. Only one row has the activated highlight at a time, no matter how many fingers I use. I do hear the sound effect, but I can get that on a `ListView` as well. – CommonsWare Jul 04 '15 at 11:16
  • Hey thanks for your interest. The problem is that i start a new thread every time user clicks on a row so if i try to multi touch the recycler's items, even in your sample app more than one threads start simultaneously and unexpected results happen. This doesn't happen with the simple ListView though. Edit i didn't make myself clear about your app indeed only one row is highlighted each time but the events are triggered anyways and it seems like they get executed one by one – ThanosFisherman Jul 04 '15 at 14:47

2 Answers2

22

To disable multi touch in recyclerview, you can use android:splitMotionEvents="false" in your recyclerview tag in layout file. By that attribute, you will not receive multi touch in recyclerview.

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
Sai Soe Harn
  • 361
  • 2
  • 6
2

The problem is that i start a new thread every time user clicks on a row so if i try to multi touch the recycler's items, even in your sample app more than one threads start simultaneously and unexpected results happen.

That has nothing to do with multi-touch. You would get the same effect with one finger, rapidly tapping on different rows. It may be easier for you to reproduce the effect via multi-touch, but there is no guarantee that the user will never tap a second row while the thread for your first row is still outstanding.

Your problem is with your implementation. Either:

  • Tapping on multiple rows in rapid succession is fine, and you need to fix the "unexpected results", such as serializing the threads, having a single thread and a LinkedBlockingQueue, or synchronizing access to shared data, or

  • Tapping on multiple rows in rapid succession is not fine, in which case you would need to track whether a thread is outstanding when the user taps on a row, then decide what to do (discard the event? queue the work to be done, so it is performed after the current thread is done? something else?).

Another possibility would be to get rid of the "fork a thread on a list row click" entirely, and require a more positive step (e.g., click some Done button) before you do whatever work it is that you are trying to do.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Yes you are right about rapid row tapping I just want to trigger only one thread possibly the one that was tapped first or last will LinkedBlockingQueue help? Never heard of that before – ThanosFisherman Jul 04 '15 at 15:16
  • 1
    @ThanosF: Basically, if you want all the events, but to process only one at a time, you need a queue. The classic Java solution would be a thread that is tied to a `LinkedBlockingQueue`, possibly by means of a single-thread `ThreadPoolExecutor`. – CommonsWare Jul 04 '15 at 15:22
  • Thanks I'm gonna have to check those things out – ThanosFisherman Jul 04 '15 at 15:26