focus-trap
Keyboard users should be able to reach and exit any UI part that contains controls or form elements.
Description
Focus trap refers to a situation where keyboard users are stuck in a focus loop within a component or a section of the UI that does not allow them to move forward or backward to other parts of the UI.
This usually happens when focus management is not handled correctly using the "nextFocusFowrard" attribute.
Quick Fixes
Android (.xml):
Default Order
To preserve the default focus order, do not set any 'nextFocus' attribute to any view on a screen. As a result, the focus will move in a natural order: from the top left view to the bottom right.
With overrides to the default order
To make the user specified focus order, set to the one or more views one of the next focus attributes, depending on your needs:
(nextFocusLeft, nextFocusRight, nextFocusUp, nextFocusDown, nextFocusForward)
1 → 2 → 3
1<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"2 android:layout_width="match_parent"3 android:layout_height="match_parent"4 android:orientation="vertical"5 android:padding="16dp">67 <Button8 android:id="@+id/button1"9 android:text="Button 1"10 android:layout_width="wrap_content"11 android:layout_height="wrap_content"12 android:nextFocusDown="@+id/button2"13 android:layout_marginBottom="8dp" />1415 <Button16 android:id="@+id/button2"17 android:text="Button 2"18 android:layout_width="wrap_content"19 android:layout_height="wrap_content"20 android:nextFocusDown="@+id/button3"21 android:layout_marginBottom="8dp" />2223 <Button24 android:id="@+id/button3"25 android:text="Button 3"26 android:layout_width="wrap_content"27 android:layout_height="wrap_content"28 android:nextFocusDown="@+id/button1" />2930</LinearLayout>
Android (Java):
Java Code (you can use one or all, this is just the sample, depending on the direction.
1 // Set next focus directions for button12 button1.setNextFocusDownId(R.id.button2);3 button1.setNextFocusUpId(R.id.button3);4 button1.setNextFocusLeftId(R.id.button3);5 button1.setNextFocusRightId(R.id.button2);6 button1.setNextFocusForwardId(R.id.button2);78 // Set next focus directions for button29 button2.setNextFocusDownId(R.id.button3);10 button2.setNextFocusUpId(R.id.button1);11 button2.setNextFocusLeftId(R.id.button1);12 button2.setNextFocusRightId(R.id.button3);13 button2.setNextFocusForwardId(R.id.button3);1415 // Set next focus directions for button316 button3.setNextFocusDownId(R.id.button1);17 button3.setNextFocusUpId(R.id.button2);18 button3.setNextFocusLeftId(R.id.button2);19 button3.setNextFocusRightId(R.id.button1);20 button3.setNextFocusForwardId(R.id.button1);
Android (Kotlin):
1 // Set next focus directions for button12 button1.nextFocusDownId = R.id.button23 button1.nextFocusUpId = R.id.button34 button1.nextFocusLeftId = R.id.button35 button1.nextFocusRightId = R.id.button26 button1.nextFocusForwardId = R.id.button278 // Set next focus directions for button29 button2.nextFocusDownId = R.id.button310 button2.nextFocusUpId = R.id.button111 button2.nextFocusLeftId = R.id.button112 button2.nextFocusRightId = R.id.button313 button2.nextFocusForwardId = R.id.button31415 // Set next focus directions for button316 button3.nextFocusDownId = R.id.button117 button3.nextFocusUpId = R.id.button218 button3.nextFocusLeftId = R.id.button219 button3.nextFocusRightId = R.id.button120 button3.nextFocusForwardId = R.id.button1
Fail example
This is a particular case of a User Specified Order when the current view creates a loop, either by itself or through a chain of user-specified orders.
1 → 2 → 1
1<Button2 android:id="@+id/button1"3 android:text="Button 1"4 android:layout_width="wrap_content"5 android:layout_height="wrap_content"6 android:nextFocusDown="@+id/button2"7 android:layout_marginBottom="8dp" />89 <Button10 android:id="@+id/button2"11 android:text="Button 2"12 android:layout_width="wrap_content"13 android:layout_height="wrap_content"14 android:nextFocusDown="@+id/button1"15 android:layout_marginBottom="8dp" />1617 <Button18 android:id="@+id/button3"19 android:text="Button 3"20 android:layout_width="wrap_content"21 android:layout_height="wrap_content" />
1 → 3 → 1 The current implementation does not support cases when several views point to the same view. In this scenario, an internal error is thrown, and the focus trap is not displayed.
How Users Are Affected
Keyboard users may be unable to reach and operate all the UI parts.
WCAG Success criteria
This issue might cause elements to fail one or more of the following Success criteria:
2.1.2 No Keyboard Trap (A)