Search code examples
androidkotlinandroid-jetpack-composeandroid-textinputlayoutandroid-compose-textfield

Equivalent of "expandedHintEnabled" in Jetpack Compose TextField


Is there any way to put OutlinedTextField's label on top (expanded) and still have the placeholder, when OutlinedTextField is not in focus?

In xml layouts we have TextInputLayout that has expandedHintEnabled attribute that does the expanding.

enter image description here


Solution

  • Currently the placeholder applies an alpha modifier with this condition InputPhase.UnfocusedEmpty -> if (showLabel) 0f else 1f and there isn't a parameter to achieve the same behaviour of expandedHintEnabled.

    A workaround can be to use a visualTransformation to display a placeholder when the text is empty, removing the placeholder parameter.

    Something like:

        val textColor = if (text.isEmpty())
            MaterialTheme.colors.onSurface.copy(ContentAlpha.medium)
        else
            LocalContentColor.current.copy(LocalContentAlpha.current)
    
        val textStyle = if (text.isEmpty())
            LocalTextStyle.current.merge(MaterialTheme.typography.subtitle1)
        else
            LocalTextStyle.current
    
        TextField(
            value = text,
            onValueChange = { text = it },
            //placeholder = { Text("Placeholder") },
            label = { Text("Label") },
            visualTransformation = if (text.isEmpty())
                PlaceholderTransformation("Placeholder")
            else VisualTransformation.None,
            textStyle = textStyle,
            colors = TextFieldDefaults.textFieldColors(
                textColor = textColor
            )
        )
    

    enter image description here

    with:

    class PlaceholderTransformation(val placeholder: String) : VisualTransformation {
        override fun filter(text: AnnotatedString): TransformedText {
            return PlaceholderFilter(text, placeholder)
        }
    }
    
    fun PlaceholderFilter(text: AnnotatedString, placeholder: String): TransformedText {
    
        val numberOffsetTranslator = object : OffsetMapping {
            override fun originalToTransformed(offset: Int): Int {
                return 0
            }
    
            override fun transformedToOriginal(offset: Int): Int {
                return 0
            }
        }
    
        return TransformedText(AnnotatedString(placeholder), numberOffsetTranslator)
    }