Closed wznshuai closed 1 year ago
Made repo with this reproducer: https://github.com/dima-avdeev-jb/desktop-bug-textfield-focus
On Android, this works fine.
There do seem to be some bugs visible with your example (caret remains in the textfield but it has not focus), and our API is not very intuitive, which we intend to improve. However, the right way to achieve what you want is:
modifier = Modifier.focusProperties {
canFocus = false
},
LaunchedEffect(Unit){
focusRequester.requestFocus()
}
val coroutineScope = rememberCoroutineScope()
...
modifier = Modifier
.onFocusChanged {
if (!it.hasFocus){
coroutineScope.launch{
focusRequester.requestFocus()
}
}
}
Here's the complete example:
@Composable
fun App() {
var text by remember { mutableStateOf("Hello, World!") }
val focusRequester = FocusRequester()
MaterialTheme {
Row {
Button(
modifier = Modifier.focusProperties {
canFocus = false
},
onClick = {
text = "Hello, Desktop!"
}
) {
Text(text)
}
val coroutineScope = rememberCoroutineScope()
TextField(
value = text,
onValueChange = { text = it },
modifier = Modifier
.focusRequester(focusRequester)
.onFocusChanged {
if (!it.hasFocus){
coroutineScope.launch{
focusRequester.requestFocus()
}
}
}
)
LaunchedEffect(Unit){
focusRequester.requestFocus()
}
}
}
}
There do seem to be some bugs visible with your example (caret remains in the textfield but it has not focus), and our API is not very intuitive, which we intend to improve. However, the right way to achieve what you want is:
To prevent the button from being focusable
modifier = Modifier.focusProperties { canFocus = false },
To grant initial focus to the text field
LaunchedEffect(Unit){ focusRequester.requestFocus() }
To return focus to the textfield if it loses it (although I wouldn't recommend doing that)
val coroutineScope = rememberCoroutineScope() ... modifier = Modifier .onFocusChanged { if (!it.hasFocus){ coroutineScope.launch{ focusRequester.requestFocus() } } }
Here's the complete example:
@Composable fun App() { var text by remember { mutableStateOf("Hello, World!") } val focusRequester = FocusRequester() MaterialTheme { Row { Button( modifier = Modifier.focusProperties { canFocus = false }, onClick = { text = "Hello, Desktop!" } ) { Text(text) } val coroutineScope = rememberCoroutineScope() TextField( value = text, onValueChange = { text = it }, modifier = Modifier .focusRequester(focusRequester) .onFocusChanged { if (!it.hasFocus){ coroutineScope.launch{ focusRequester.requestFocus() } } } ) LaunchedEffect(Unit){ focusRequester.requestFocus() } } } }
as you said,API is not very intuitive. However, I think that if requestFocus succeeds, other widgets should lose focus
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.
Select one of the platforms below: Desktop
Versions Kotlin version: 1.8.0 Compose Multiplatform version: 1.3.0 JDK (for desktop issues): 16
I need textfield auto request focus when lose focus. i add code like this:
when i click the button, i can't input any in textfield