Modify accessibility focus order
For applications with minSdkVersion >= 22, you may set the traversal order for screen readers direct in the XML with android:accessibilityTraversalAfter:
<ImageView
android:id="@+id/imageView"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_launcher" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="30dp"
android:accessibilityTraversalAfter="@id/imageView3"
android:layout_height="30dp"
android:src="@drawable/ic_launcher" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_launcher" />
For applications supporting lower API levels, the traversal order may be set programmatically with ViewCompat:
ViewCompat.setAccessibilityDelegate(imageView2, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(host: View?, info: AccessibilityNodeInfoCompat?) {
info?.setTraversalAfter(imageView3)
super.onInitializeAccessibilityNodeInfo(host, info)
}
})
Please keep in mind that screen reader users rely on the consistency of the navigation, therefore, changing the focus order is an anti-pattern and should be avoided.
Related videos on Youtube
Allen Z.
Updated on April 19, 2021Comments
-
Allen Z. about 3 years
Is it possible to change the accessibility focus order? For example, if I have 3 views side by side, with ids view1, view2, and view3, is there a simple way to make the accessibility focus go to view3 when the user swipes right from view1?
Here is what I've tried:
I have the following in a linear layout.
<ImageView android:layout_width="30dp" android:layout_height="30dp" android:id="@+id/imageView" android:focusable="true" android:nextFocusUp="@+id/imageView3" android:nextFocusDown="@+id/imageView3" android:nextFocusRight="@+id/imageView3" android:nextFocusLeft="@+id/imageView3" android:nextFocusForward="@+id/imageView3" android:src="@drawable/ic_launcher"/> <ImageView android:layout_width="30dp" android:layout_height="30dp" android:id="@+id/imageView2" android:focusable="true" android:src="@drawable/ic_launcher"/> <ImageView android:layout_width="30dp" android:layout_height="30dp" android:id="@+id/imageView3" android:focusable="true" android:nextFocusUp="@+id/imageView2" android:nextFocusDown="@+id/imageView2" android:nextFocusRight="@+id/imageView2" android:nextFocusLeft="@+id/imageView2" android:nextFocusForward="@+id/imageView2" android:src="@drawable/ic_launcher"/>
Then, I launch this and place accessibility focus on the first imageView. Upon swiping right to move to the next item, I expect it to move accessibility focus to imageView3, but instead it goes to imageView2.
-
alanv over 9 yearsTechnically yes, you can explicitly specify traversal order if you set an AccessibilityDelegate and add the child nodes manually, but this causes other issues and isn't guaranteed to work if TalkBack changes how it handles focus traversal. It's still an open feature request against the accessibility framework.
-
Kio Krofovitch about 9 years@alanv Do you happen to have a link to the outstanding feature request? I'd love to follow its' progress. Changing the traversal order would be especially helpful for the new Floating Action Button. If it is floating over an auto-loading list, a user might not ever find it by swiping right. (See Inbox for example of this issue)
-
Kio Krofovitch about 9 yearsNevermind, looks like it was just added in API 22! Added an answer to the original quesiton.
-
-
vtlinh over 7 yearsIs there any solution for this for versions < 22?
-
Carlos about 7 yearsI think @vtlinh question is even more important than the original one. 22 is too recent. Does anyone know what's the solution for older versions?
-
azizbekian almost 7 yearsI experience issues using this in a
RecyclerView
item. It jumps to next item of the list after traversing on current item. -
user3829751 over 6 years@Carlos @vtlinh It seems there is a compat class for it: AccessibilityNodeInfoCompat. It contains methods
setTraversalBefore
andsetTraversalAfter
-
Saurabh over 4 yearsfor anyone trying this, it only work >= 22. Their is no solution for <22.
-
Nicolás Arias about 4 yearsIn case image3 is gone this won't work. Is there some way to solve this?
-
Dr.jacky over 2 yearsDidn't work for me, neither
setTraversalAfter
norsetTraversalBefore
. Still reads as A1, B1, A2, C1, B2. But what I want is A1, A2, B1, B2, C1; where A1 is a textview on left and A2 is a textview on the right side, B1B2 the same but under A1A2, etc; all under aConstraintLayout
.