Allen Z.
Allen Z.

Reputation: 350

Modify accessibility focus order

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.

Upvotes: 26

Views: 35717

Answers (2)

JTODR
JTODR

Reputation: 338

Updated answer (as of 2024) to set accessibility focus traversal for API 22 or lower is:

    ViewCompat.setAccessibilityDelegate(imageView2, object : AccessibilityDelegateCompat() {
        override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
            info.setTraversalAfter(imageView3)
            super.onInitializeAccessibilityNodeInfo(host, info)
        }
    })

Upvotes: 0

Kio Krofovitch
Kio Krofovitch

Reputation: 3022

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.

Upvotes: 50

Related Questions