androidandroid-jetpack-composeandroid-compose-textfield

TextField passed in lambda loses focus when in both branches of "if" block


I have some content with textfields passed as a lambda to another composable. Lambda is always a part of layout as it's in both branches of if statement, however when condition of 'if' changes - text fields lose focus. Is there any way to prevent it while keeping current structure?

versions: compose = "2024.06.00" compose-compiler = "1.5.14"

Real use case: two complex container layouts for tablet/mobile that accept main content as lambda. Containers switched based of screen size.

Simplified example:

                    val condition = remember { mutableStateOf(false) }
                    val content = @Composable {
                        TextField(value = "", onValueChange = {})
                    }

                    LaunchedEffect(Unit) {
                        while (isActive) {
                            delay(1000)
                            condition.value = !condition.value
                        }
                    }

                    Column {
                        if (condition.value) {
                            content()
                        } else {
                            content()
                        }
                    }

Solution

  • Although content is the same in both branches of the if, for the Compose runtime they are two different, unrelated composables. When one has the focus and the condition changes so the other is displayed instead, the other doesn't automatically inherits the focus from the first.

    If the content would have an internal state (like a remembered mutableStateOf), that would also be different. You should restructure your code so that content is only called once, then the TextField would keep the focus state.