1

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

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
mrzbn
  • 497
  • 1
  • 3
  • 15

1 Answers1

1

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 {

    var out = placeholder

    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)
}
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Thanks, this works. What about if we want to put label always on top, without focus? (no placeholder) – mrzbn Feb 01 '23 at 07:41