I noticed that if I have multiple multi-line BasicTextField
in a Column
, if one the text fields has focus and I press the up and down arrow keys on my physical keyboard (using Android Studio emulator), the focus is moved to a different text field instead of going up or down to a different line of text within the text field.
I kind of like the idea of letting the up and down arrow keys change focus, but only if the cursor is at the first or last line.
I came up with a solution, but I am wondering if there is an easier way to do this. Also, if I want to allow a change of focus using arrow keys AND through other methods, it seems I would have to modify this somehow to check the key that was pressed with one of those key modifiers, but I am not sure the best way to do that. Do you know how to determine if a key press is also triggering focus movement/change?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column {
repeat(5) {
BasicTextFieldWithText()
}
}
}
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun BasicTextFieldWithText() {
var text by remember {
mutableStateOf(
TextFieldValue("BasicTextField\n" + "with multiple lines\n" + "of text")
)
}
var textLayout by remember {
mutableStateOf<TextLayoutResult?>(null)
}
val atFirstLine by remember {
derivedStateOf {
textLayout?.let {
val range = text.selection
range.collapsed && it.getLineForOffset(range.end) == 0
} ?: false
}
}
val atLastLine by remember {
derivedStateOf {
textLayout?.let {
val range = text.selection
range.collapsed && it.getLineForOffset(range.end) == (it.lineCount - 1)
} ?: false
}
}
BasicTextField(
value = text,
onValueChange = { text = it },
onTextLayout = { textLayout = it },
modifier = Modifier
.border(1.dp, Color.Blue)
.padding(8.dp)
.focusProperties {
up = if (atFirstLine) FocusRequester.Default else FocusRequester.Cancel
down = if (atLastLine) FocusRequester.Default else FocusRequester.Cancel
}
)
}