Composable Component

TextField

Text fields allow users to enter text into a UI.

TextField social preview

DenseTextFieldContentPadding

@Preview
@Composable
fun DenseTextFieldContentPadding() {
    TextField(
        state = rememberTextFieldState(),
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        // Need to set a min height using `heightIn` to override the default
        modifier = Modifier.heightIn(min = 48.dp),
        contentPadding = PaddingValues(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp),
    )
}

SimpleTextFieldSample

@Preview
@Composable
fun SimpleTextFieldSample() {
    TextField(
        state = rememberTextFieldState(),
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
    )
}

TextFieldWithErrorState

@Preview
@Composable
fun TextFieldWithErrorState() {
    val errorMessage = "Text input too long"
    val state = rememberTextFieldState()
    var isError by rememberSaveable { mutableStateOf(false) }
    val charLimit = 10
    fun validate(text: CharSequence) {
        isError = text.length > charLimit
    }
    LaunchedEffect(Unit) {
        // Run validation whenever text value changes
        snapshotFlow { state.text }.collect { validate(it) }
    }
    TextField(
        state = state,
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text(if (isError) "Username*" else "Username") },
        supportingText = {
            Row {
                Text(if (isError) errorMessage else "", Modifier.clearAndSetSemantics {})
                Spacer(Modifier.weight(1f))
                Text("Limit: ${state.text.length}/$charLimit")
            }
        },
        isError = isError,
        onKeyboardAction = { validate(state.text) },
        modifier =
            Modifier.semantics {
                maxTextLength = charLimit
                // Provide localized description of the error
                if (isError) error(errorMessage)
            },
    )
}

TextFieldWithHideKeyboardOnImeAction

@Preview
@Composable
fun TextFieldWithHideKeyboardOnImeAction() {
    val keyboardController = LocalSoftwareKeyboardController.current
    TextField(
        state = rememberTextFieldState(),
        label = { Text("Label") },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
        onKeyboardAction = { keyboardController?.hide() },
    )
}

TextFieldWithIcons

@Preview
@Composable
fun TextFieldWithIcons() {
    val state = rememberTextFieldState()
    TextField(
        state = state,
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        leadingIcon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
        trailingIcon = {
            TooltipBox(
                positionProvider =
                    TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
                tooltip = { PlainTooltip { Text("Clear text") } },
                state = rememberTooltipState(),
            ) {
                IconButton(onClick = { state.clearText() }) {
                    Icon(Icons.Filled.Clear, contentDescription = "Clear text")
                }
            }
        },
    )
}

TextFieldWithInitialValueAndSelection

@Preview
@Composable
fun TextFieldWithInitialValueAndSelection() {
    val state = rememberTextFieldState("Initial text", TextRange(0, 12))
    TextField(state = state, lineLimits = TextFieldLineLimits.SingleLine, label = { Text("Label") })
}

TextFieldWithPlaceholder

@Preview
@Composable
fun TextFieldWithPlaceholder() {
    var alwaysMinimizeLabel by remember { mutableStateOf(false) }
    Column {
        Row {
            Checkbox(checked = alwaysMinimizeLabel, onCheckedChange = { alwaysMinimizeLabel = it })
            Text("Show placeholder even when unfocused")
        }
        Spacer(Modifier.height(16.dp))
        TextField(
            state = rememberTextFieldState(),
            lineLimits = TextFieldLineLimits.SingleLine,
            label = { Text("Email") },
            labelPosition = TextFieldLabelPosition.Attached(alwaysMinimize = alwaysMinimizeLabel),
            placeholder = { Text("[email protected]") },
        )
    }
}

TextFieldWithPrefixAndSuffix

@Preview
@Composable
fun TextFieldWithPrefixAndSuffix() {
    var alwaysMinimizeLabel by remember { mutableStateOf(false) }
    Column {
        Row {
            Checkbox(checked = alwaysMinimizeLabel, onCheckedChange = { alwaysMinimizeLabel = it })
            Text("Show placeholder even when unfocused")
        }
        Spacer(Modifier.height(16.dp))
        TextField(
            state = rememberTextFieldState(),
            lineLimits = TextFieldLineLimits.SingleLine,
            label = { Text("Label") },
            labelPosition = TextFieldLabelPosition.Attached(alwaysMinimize = alwaysMinimizeLabel),
            prefix = { Text("www.") },
            suffix = { Text(".com") },
            placeholder = { Text("google") },
        )
    }
}

TextFieldWithSupportingText

@Preview
@Composable
fun TextFieldWithSupportingText() {
    TextField(
        state = rememberTextFieldState(),
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        supportingText = {
            Text("Supporting text that is long and perhaps goes onto another line.")
        },
    )
}

TextFieldWithTransformations

@Preview
@Composable
fun TextFieldWithTransformations() {
    TextField(
        state = rememberTextFieldState(),
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Phone number") },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
        // Input transformation to limit user input to 10 digits
        inputTransformation =
            InputTransformation.maxLength(10).then {
                if (!this.asCharSequence().isDigitsOnly()) {
                    revertAllChanges()
                }
            },
        outputTransformation = {
            // Output transformation to format as a phone number: (XXX) XXX-XXXX
            if (length > 0) insert(0, "(")
            if (length > 4) insert(4, ") ")
            if (length > 9) insert(9, "-")
        },
    )
}