@ -6,13 +6,12 @@ In this tutorial, we will show you how to use tabbing navigation between compone
## Default `Next/Previous` tabbing navigation
## Default `Next/Previous` tabbing navigation
By default, `Next/Previous` tabbed navigation moves focus in composition order (in order of appearance), to see how this works, we can use some of the components that are already focusable by default:`TextField`, `OutlinedTextField` , `BasicTextField` , `CircularProgressIndicator` , `LinearProgressIndicator` .
By default, `Next/Previous` tabbed navigation moves focus in composition order (in order of appearance), to see how this works, we can use some of the components that are already focusable by default: `TextField` , `OutlinedTextField` , `BasicTextField` , components with `Modifier.clickable` (`Button`, `IconButton` , `MenuItem` ) .
```kotlin
```kotlin
import androidx.compose.ui.window.application
import androidx.compose.ui.window.application
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowSize
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxSize
@ -24,11 +23,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
fun main() = application {
fun main() = application {
Window(
Window(
state = WindowState(size = Window Size(350.dp, 500.dp)),
state = WindowState(size = Dp Size(350.dp, 500.dp)),
onCloseRequest = ::exitApplication
onCloseRequest = ::exitApplication
) {
) {
Box(
Box(
@ -58,12 +58,10 @@ fun main() = application {
To make a non-focusable component focusable, you need to apply `Modifier.focusable()` modifier to the component.
To make a non-focusable component focusable, you need to apply `Modifier.focusable()` modifier to the component.
```kotlin
```kotlin
import androidx.compose.foundation.background
import androidx.compose.ui.window.application
import androidx.compose.ui.window.application
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowSize
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.Text
import androidx.compose.foundation.focusable
import androidx.compose.foundation.focusable
@ -76,6 +74,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.remember
@ -84,17 +83,17 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.key.*
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.onPointerEvent
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.input.key.type
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.onPreviewKeyEvent
fun main() = application {
fun main() = application {
Window(
Window(
state = WindowState(size = Window Size(350.dp, 450.dp)),
state = WindowState(size = DpSize(350.dp, 450.dp)),
onCloseRequest = ::exitApplication
onCloseRequest = ::exitApplication
) {
) {
MaterialTheme(
MaterialTheme(
@ -114,7 +113,7 @@ fun main() = application {
Text(text = "Clicks: ${clicks.value}")
Text(text = "Clicks: ${clicks.value}")
Spacer(modifier = Modifier.height(20.dp))
Spacer(modifier = Modifier.height(20.dp))
for (x in 1..5) {
for (x in 1..5) {
FocusableButton ("Button $x", { clicks.value++ })
FocusableBox ("Button $x", { clicks.value++ })
Spacer(modifier = Modifier.height(20.dp))
Spacer(modifier = Modifier.height(20.dp))
}
}
}
}
@ -125,27 +124,27 @@ fun main() = application {
@OptIn (ExperimentalComposeUiApi::class)
@OptIn (ExperimentalComposeUiApi::class)
@Composable
@Composable
fun FocusableButton (
fun FocusableBox (
text: String = "",
text: String = "",
onClick: () -> Unit = {},
onClick: () -> Unit = {},
size: IntSize = IntSize(200, 35)
size: IntSize = IntSize(200, 35)
) {
) {
val keyPressedState = remember { mutableStateOf(false) }
val keyPressedState = remember { mutableStateOf(false) }
val interactionSource = remember { MutableInteractionSource() }
val interactionSource = remember { MutableInteractionSource() }
val colors = ButtonDefaults.buttonColors(
val backgroundColor = if (interactionSource.collectIsFocusedAsState().value) {
backgroundColor = if (interactionSource.collectIsFocusedAsState().value) {
if (keyPressedState.value)
if (keyPressedState.value )
lerp(MaterialTheme.colors.secondary, Color(64, 64, 64), 0.3f )
l erp(Materia lTheme.colors. secondary, Color(64, 64, 64), 0.3f)
else
else
Mat eria lTheme.colors. secondary
MaterialTheme.colors.secondary
} else {
} else {
MaterialTheme.colors.primary
MaterialTheme.colors.primary
}
}
Box(
)
modifier = Modifier
Button(
.clip(RoundedCornerShape(4.dp))
onClick = onClick,
.background(backgroundColor)
interactionSource = interactionSource,
.size(size.width.dp, size.height.dp)
modifier = Modifier.size(size.width.dp, size.height.dp)
.onPointerEvent(PointerEventType.Press) { onClick() }
.onPreviewKeyEvent {
.onPreviewKeyEvent {
if (
if (
it.key == Key.Enter ||
it.key == Key.Enter ||
@ -164,9 +163,9 @@ fun FocusableButton(
false
false
}
}
.focusable(interactionSource = interactionSource),
.focusable(interactionSource = interactionSource),
colors = colors
contentAlignment = Alignment.Center
) {
) {
Text(text = text)
Text(text = text, color = Color.White )
}
}
}
}
```
```
@ -185,7 +184,6 @@ In the example below, we simply create a `FocusRequester` list and create text f
import androidx.compose.ui.window.application
import androidx.compose.ui.window.application
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowSize
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxSize
@ -199,11 +197,12 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusOrder
import androidx.compose.ui.focus.focusOrder
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
fun main() = application {
fun main() = application {
Window(
Window(
state = WindowState(size = Window Size(350.dp, 500.dp)),
state = WindowState(size = Dp Size(350.dp, 500.dp)),
onCloseRequest = ::exitApplication
onCloseRequest = ::exitApplication
) {
) {
val itemsList = remember { List(5) { FocusRequester() } }
val itemsList = remember { List(5) { FocusRequester() } }
@ -309,4 +308,4 @@ fun main() = application {
}
}
```
```
< img alt = "reverse-order" src = "focus-switcher.gif" height = "480" / >
< img alt = "reverse-order" src = "focus-switcher.gif" height = "480" / >