Seb and Ataul were working on some accessibility improvements to the All-4 Android app and came across a RecyclerView
focus bug.
One of the areas we're... focusing on at Novoda is to increase support for vision impaired users in our apps. A common use case is to perform some action on a list item in place—for example marking a Tweet as favourite or starring a To-do.
We found that a RecyclerView
would lose its focus when you update the data backing its adapter. This happens for both view focus and accessibility focus (with a switch or screenreader). The former is the one you have when using a D-Pad or a trackball to navigate; the latter is the one that comes up when the user is using TalkBack, or a switch.
Here's how the issue looks like for a user:
For users that rely on interacting with focusable elements this is extremely annoying and time consuming. It might make navigation impossible.
Luckily, this is not the intended behaviour, but rather "just" a RecyclerView
item animator bug. A workaround exists to avoid the issue by disabling the item animations:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
if (needToRetainFocusOnItemChange()) {
recyclerView.setItemAnimator(null);
}
For this to work, if you use adapter.notifyDataSetChanged()
then your adapter also needs to support stable IDs (setHasStableIds(true)
), and implement long getItemId(int position)
.
If you're using adapter.notifyItem*()
then you're good with just removing the animator.
As pointed out in the bug report, in the latter case you can also just disable the "change" item animation.
Thanks to Yigit Boyar for the heads up!
We plan, design, and develop the world’s most desirable software products. Our team’s expertise helps
brands like Sony, Motorola, Tesco, Channel4, BBC, and News Corp build fully customized Android devices
or simply make their mobile experiences the best on the market. Since 2008, our full in-house teams work
from London, Liverpool, Berlin, Barcelona, and NYC.
Let’s get in contact