'Android Jetpack Compose AnimatedVisibility innerTextField of BasicTextField

I'm receiving the following errors when tapping to focus on my BasicTextField after an animation has run. Please help.

decorationBox = { innerTextField ->
    Box(Modifier.weight(1f)) {
        if (addressText.isEmpty()) {
            Label3(dynamicId = structure?.placeholder)
        }
        AnimatedVisibility(
            visible = focusAddress
        ) {
            innerTextField()
        }
    }
},

E/InputConnectionWrapper: InputConnectionWrapper.waitForInputConnectionFutureInternal():1542 Failed to get the input connection call's result.

java.lang.IllegalStateException: LayoutCoordinate operations are only valid when isAttached is true

EDIT: It can be reproduced if the text field gains, looses and gains focus again. Issue is that coreTextField() is not available. Here is a short example which produces the same error message:

@Composable
fun TextInput(
    modifier: Modifier = Modifier,
    value: String,
    label: String,
    onValueChanged: (text: String) -> Unit,
) {
    var textFieldValueState by remember { mutableStateOf(TextFieldValue(text = value)) }
    val textFieldValue = textFieldValueState.copy(text = value)

    val interactionSource = remember { MutableInteractionSource() }
    val isFocused = interactionSource.collectIsFocusedAsState().value

    BasicTextField(
        value = textFieldValue,
        modifier = modifier
            .defaultMinSize(
                minWidth = TextFieldDefaults.MinWidth,
                minHeight = TextFieldDefaults.MinHeight,
            ),
        onValueChange = {
            textFieldValueState = it
            if (value != it.text) {
                onValueChanged(it.text)
            }
        },
        interactionSource = interactionSource,
        decorationBox = @Composable { coreTextField ->
            Surface(
                shape = RoundedCornerShape(),
                border = BorderStroke(
                    width = 2.dp,
                    color = Colors.Black,
                )
            ) {
                Column(
                    modifier = Modifier
                        .height(52.dp)
                        .padding(horizontal = 16.dp, vertical = 8.dp),
                    horizontalAlignment = Alignment.Start,
                    verticalArrangement = Arrangement.Center,
                ) {
                    Text(text = label)
                    if (isFocused) coreTextField()
                }
            }
        },
    )
}


Solution 1:[1]

The problem is that the BasicTextField composable contains the one defined in decorationBox so it cannot just be removed from composition with an AnimatedVisibility or a simple if (if (isFocused) coreTextField() in your example). We need something that works a bit like the old View.GONE - the composable should occupy zero space, but should still be there. And the equivalent is using a layout modifier and not placing the placeable.

I was animating those fields based on my labelProgress variable that goes from 1f to 0f, so I was changing the height of the placeable like this.

        Box(modifier = Modifier
            .alpha(labelProgress)
            .layout { measurable, constraints ->
                val placeable = measurable.measure(constraints)
                layout(placeable.width, (placeable.height * labelProgress).toInt()) {
                    placeable.placeRelative(0, 0, 0f)
                }

            }
        ) {
            innerTextField()
        }

A basic visible/hidden version would probably look something like this:

        Box(modifier = Modifier
            .layout { measurable, constraints ->
                if(showInnerTextField){
                    layout(placeable.width, (placeable.height * labelProgress).toInt()) {
                        placeable.placeRelative(0, 0, 0f)
                    }
                }

            }
        ) {
            innerTextField()
        }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1