Change focus traversal order
Stay organized with collections
Save and categorize content based on your preferences.
The Default focus traversal order section described how Compose
automatically adds focus traversal behavior to your elements, for both
one-dimensional (tab
key) and two-dimensional (arrow keys) navigation. In some
cases, you might need to override this default behavior and be more explicit
about the required traversal order.
Override one-dimensional traversal order
To change the default focus traversal order for one-dimensional navigation, you
create a set of references, one for each focusable composable:
val (first, second, third, fourth) = remember { FocusRequester.createRefs() }
Then, use the focusRequester
modifier to associate each of them with a
composable:
Column {
Row {
TextButton({}, Modifier.focusRequester(first)) { Text("First field") }
TextButton({}, Modifier.focusRequester(third)) { Text("Third field") }
}
Row {
TextButton({}, Modifier.focusRequester(second)) { Text("Second field") }
TextButton({}, Modifier.focusRequester(fourth)) { Text("Fourth field") }
}
}
You can now use the focusProperties
modifier to specify a custom traversal order:
Column {
Row {
TextButton(
{},
Modifier
.focusRequester(first)
.focusProperties { next = second }
) {
Text("First field")
}
TextButton(
{},
Modifier
.focusRequester(third)
.focusProperties { next = fourth }
) {
Text("Third field")
}
}
Row {
TextButton(
{},
Modifier
.focusRequester(second)
.focusProperties { next = third }
) {
Text("Second field")
}
TextButton(
{},
Modifier
.focusRequester(fourth)
.focusProperties { next = first }
) {
Text("Fourth field")
}
}
}
Override two-dimensional traversal order
It is also possible to add fine-grained control over the focus traversal order
for two-dimensional navigation with the arrow keys. For each element, you can
override the default navigation destination for each of the directions by adding
the focusProperties
modifier and specifying the item that would come up,
down, or any other direction:
TextButton(
onClick = {},
modifier = Modifier
.focusRequester(fourth)
.focusProperties {
down = third
right = second
}
) {}
This technique not only effectively uses keyboard arrows, but would work with
D-Pads and sticks on wired and wireless controllers.
Recommended for you
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-05-20 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-05-20 UTC."],[],[],null,["# Change focus traversal order\n\nThe [Default focus traversal order](/develop/ui/compose/touch-input/focus) section described how Compose\nautomatically adds focus traversal behavior to your elements, for both\none-dimensional (`tab` key) and two-dimensional (arrow keys) navigation. In some\ncases, you might need to override this default behavior and be more explicit\nabout the required traversal order.\n\nOverride one-dimensional traversal order\n----------------------------------------\n\nTo change the default focus traversal order for one-dimensional navigation, you\ncreate a set of references, one for each focusable composable:\n\n\n```kotlin\nval (first, second, third, fourth) = remember { FocusRequester.createRefs() }https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L119-L119\n```\n\n\u003cbr /\u003e\n\nThen, use the [`focusRequester`](/reference/kotlin/androidx/compose/ui/focus/package-summary#(androidx.compose.ui.Modifier).focusRequester(androidx.compose.ui.focus.FocusRequester)) modifier to associate each of them with a\ncomposable:\n\n\n```kotlin\nColumn {\n Row {\n TextButton({}, Modifier.focusRequester(first)) { Text(\"First field\") }\n TextButton({}, Modifier.focusRequester(third)) { Text(\"Third field\") }\n }\n\n Row {\n TextButton({}, Modifier.focusRequester(second)) { Text(\"Second field\") }\n TextButton({}, Modifier.focusRequester(fourth)) { Text(\"Fourth field\") }\n }\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L122-L132\n```\n\n\u003cbr /\u003e\n\nYou can now use the [`focusProperties`](/reference/kotlin/androidx/compose/ui/focus/package-summary#(androidx.compose.ui.Modifier).focusProperties(kotlin.Function1)) modifier to specify a custom traversal order:\n\n\n```kotlin\nColumn {\n Row {\n TextButton(\n {},\n Modifier\n .focusRequester(first)\n .focusProperties { next = second }\n ) {\n Text(\"First field\")\n }\n TextButton(\n {},\n Modifier\n .focusRequester(third)\n .focusProperties { next = fourth }\n ) {\n Text(\"Third field\")\n }\n }\n\n Row {\n TextButton(\n {},\n Modifier\n .focusRequester(second)\n .focusProperties { next = third }\n ) {\n Text(\"Second field\")\n }\n TextButton(\n {},\n Modifier\n .focusRequester(fourth)\n .focusProperties { next = first }\n ) {\n Text(\"Fourth field\")\n }\n }\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L136-L174\n```\n\n\u003cbr /\u003e\n\nOverride two-dimensional traversal order\n----------------------------------------\n\nIt is also possible to add fine-grained control over the focus traversal order\nfor two-dimensional navigation with the arrow keys. For each element, you can\noverride the default navigation destination for each of the directions by adding\nthe [`focusProperties`](/reference/kotlin/androidx/compose/ui/focus/package-summary#(androidx.compose.ui.Modifier).focusProperties(kotlin.Function1)) modifier and specifying the item that would come up,\ndown, or any other direction:\n\n\n```kotlin\nTextButton(\n onClick = {},\n modifier = Modifier\n .focusRequester(fourth)\n .focusProperties {\n down = third\n right = second\n }\n) {}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/focus/FocusSnippets.kt#L185-L193\n```\n\n\u003cbr /\u003e\n\nThis technique not only effectively uses keyboard arrows, but would work with\nD-Pads and sticks on wired and wireless controllers.\n\nRecommended for you\n-------------------\n\n- Note: link text is displayed when JavaScript is off\n- [Change focus behavior](/develop/ui/compose/touch-input/focus/change-focus-behavior)\n- [Focus in Compose](/develop/ui/compose/touch-input/focus)"]]