New Compose Multiplatform components arrived on Composables UICheck it out →

TextField

Filled text fields have more visual emphasis than outlined text fields, making them stand out when surrounded by other content and components.

Filled text field image

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material:material:1.7.0-beta03")
}

Overloads

@Composable
fun TextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    leadingIcon: @Composable (() -> Unit)? = null,
    trailingIcon: @Composable (() -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions(),
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = TextFieldDefaults.TextFieldShape,
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()
)

Parameters

namedescription
valuethe input text to be shown in the text field
onValueChangethe callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback
modifiera [Modifier] for this text field
enabledcontrols the enabled state of the [TextField]. When false, the text field will be neither editable nor focusable, the input of the text field will not be selectable, visually text field will appear in the disabled UI state
readOnlycontrols the editable state of the [TextField]. When true, the text field can not be modified, however, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that user can not edit
textStylethe style to be applied to the input text. The default [textStyle] uses the [LocalTextStyle] defined by the theme
labelthe optional label to be displayed inside the text field container. The default text style for internal [Text] is [Typography.caption] when the text field is in focus and [Typography.subtitle1] when the text field is not in focus
placeholderthe optional placeholder to be displayed when the text field is in focus and the input text is empty. The default text style for internal [Text] is [Typography.subtitle1]
leadingIconthe optional leading icon to be displayed at the beginning of the text field container
trailingIconthe optional trailing icon to be displayed at the end of the text field container
isErrorindicates if the text field's current value is in error. If set to true, the label, bottom indicator and trailing icon by default will be displayed in error color
visualTransformationtransforms the visual representation of the input [value] For example, you can use [PasswordVisualTransformation][androidx.compose.ui.text.input.PasswordVisualTransformation] to create a password text field. By default no visual transformation is applied
keyboardOptionssoftware keyboard options that contains configuration such as [KeyboardType] and [ImeAction].
keyboardActionswhen the input service emits an IME action, the corresponding callback is called. Note that this IME action may be different from what you specified in [KeyboardOptions.imeAction].
singleLinewhen set to true, this text field becomes a single horizontally scrolling text field instead of wrapping onto multiple lines. The keyboard will be informed to not show the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the maxLines attribute will be automatically set to 1.
maxLinesthe maximum height in terms of maximum number of visible lines. It is required that 1 <= [minLines] <= [maxLines]. This parameter is ignored when [singleLine] is true.
minLinesthe minimum height in terms of minimum number of visible lines. It is required that 1 <= [minLines] <= [maxLines]. This parameter is ignored when [singleLine] is true.
interactionSourcean optional hoisted [MutableInteractionSource] for observing and emitting [Interaction]s for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.
shapethe shape of the text field's container
colors[TextFieldColors] that will be used to resolve color of the text, content (including label, placeholder, leading and trailing icons, indicator line) and background for this text field in different states. See [TextFieldDefaults.textFieldColors]
@Composable
fun TextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    leadingIcon: @Composable (() -> Unit)? = null,
    trailingIcon: @Composable (() -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions(),
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = TextFieldDefaults.TextFieldShape,
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()
)

Parameters

namedescription
valuethe input [TextFieldValue] to be shown in the text field
onValueChangethe callback that is triggered when the input service updates values in [TextFieldValue]. An updated [TextFieldValue] comes as a parameter of the callback
modifiera [Modifier] for this text field
enabledcontrols the enabled state of the [TextField]. When false, the text field will be neither editable nor focusable, the input of the text field will not be selectable, visually text field will appear in the disabled UI state
readOnlycontrols the editable state of the [TextField]. When true, the text field can not be modified, however, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that user can not edit
textStylethe style to be applied to the input text. The default [textStyle] uses the [LocalTextStyle] defined by the theme
labelthe optional label to be displayed inside the text field container. The default text style for internal [Text] is [Typography.caption] when the text field is in focus and [Typography.subtitle1] when the text field is not in focus
placeholderthe optional placeholder to be displayed when the text field is in focus and the input text is empty. The default text style for internal [Text] is [Typography.subtitle1]
leadingIconthe optional leading icon to be displayed at the beginning of the text field container
trailingIconthe optional trailing icon to be displayed at the end of the text field container
isErrorindicates if the text field's current value is in error state. If set to true, the label, bottom indicator and trailing icon by default will be displayed in error color
visualTransformationtransforms the visual representation of the input [value]. For example, you can use [PasswordVisualTransformation][androidx.compose.ui.text.input.PasswordVisualTransformation] to create a password text field. By default no visual transformation is applied
keyboardOptionssoftware keyboard options that contains configuration such as [KeyboardType] and [ImeAction].
keyboardActionswhen the input service emits an IME action, the corresponding callback is called. Note that this IME action may be different from what you specified in [KeyboardOptions.imeAction].
singleLinewhen set to true, this text field becomes a single horizontally scrolling text field instead of wrapping onto multiple lines. The keyboard will be informed to not show the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the maxLines attribute will be automatically set to 1.
maxLinesthe maximum height in terms of maximum number of visible lines. It is required that 1 <= [minLines] <= [maxLines]. This parameter is ignored when [singleLine] is true.
minLinesthe minimum height in terms of minimum number of visible lines. It is required that 1 <= [minLines] <= [maxLines]. This parameter is ignored when [singleLine] is true.
interactionSourcean optional hoisted [MutableInteractionSource] for observing and emitting [Interaction]s for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.
shapethe shape of the text field's container
colors[TextFieldColors] that will be used to resolve color of the text, content (including label, placeholder, leading and trailing icons, indicator line) and background for this text field in different states. See [TextFieldDefaults.textFieldColors]
@Composable
@Deprecated(
    "Maintained for binary compatibility. Use version with minLines instead",
    level = DeprecationLevel.HIDDEN

fun TextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    leadingIcon: @Composable (() -> Unit)? = null,
    trailingIcon: @Composable (() -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions(),
    singleLine: Boolean = false,
    maxLines: Int = Int.MAX_VALUE,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    shape: Shape = TextFieldDefaults.TextFieldShape,
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()
)
@Composable
@Deprecated(
    "Maintained for binary compatibility. Use version with minLines instead",
    level = DeprecationLevel.HIDDEN

fun TextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    leadingIcon: @Composable (() -> Unit)? = null,
    trailingIcon: @Composable (() -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions(),
    singleLine: Boolean = false,
    maxLines: Int = Int.MAX_VALUE,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    shape: Shape =
        MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()
)

Code Examples

SimpleTextFieldSample

@Composable
@Sampled
fun SimpleTextFieldSample() {
    var text by rememberSaveable { mutableStateOf("") }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") },
        singleLine = true
    )
}

TextFieldWithPlaceholder

@Composable
@Sampled
fun TextFieldWithPlaceholder() {
    var text by rememberSaveable { mutableStateOf("") }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Email") },
        placeholder = { Text("example@gmail.com") }
    )
}

TextFieldWithIcons

@Composable
@Sampled
fun TextFieldWithIcons() {
    var text by rememberSaveable { mutableStateOf("") }

    TextField(
        value = text,
        onValueChange = { text = it },
        placeholder = { Text("placeholder") },
        leadingIcon = { Icon(Icons.Filled.Favorite, contentDescription = "Localized description") },
        trailingIcon = { Icon(Icons.Filled.Info, contentDescription = "Localized description") }
    )
}

TextFieldWithErrorState

@Composable
@Sampled
fun TextFieldWithErrorState() {
    var text by rememberSaveable { mutableStateOf("") }
    var isError by rememberSaveable { mutableStateOf(false) }

    fun validate(text: String) {
        isError = text.count() < 5
    }

    TextField(
        value = text,
        onValueChange = {
            text = it
            isError = false
        },
        singleLine = true,
        label = { Text(if (isError) "Email*" else "Email") },
        isError = isError,
        keyboardActions = KeyboardActions { validate(text) },
        modifier = Modifier.semantics {
            // Provide localized description of the error
            if (isError) error("Email format is invalid.")
        }
    )
}

TextFieldWithHelperMessage

@Composable
@Sampled
fun TextFieldWithHelperMessage() {
    var text by rememberSaveable { mutableStateOf("") }

    Column {
        TextField(
            value = text,
            onValueChange = { text = it },
            label = { Text("Label") }
        )
        Text(
            text = "Helper message",
            color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
            style = MaterialTheme.typography.caption,
            modifier = Modifier.padding(start = 16.dp)
        )
    }
}

PasswordTextField

@Composable
@Sampled
fun PasswordTextField() {
    var password by rememberSaveable { mutableStateOf("") }
    var passwordHidden by rememberSaveable { mutableStateOf(true) }
    TextField(
        value = password,
        onValueChange = { password = it },
        singleLine = true,
        label = { Text("Enter password") },
        visualTransformation =
        if (passwordHidden) PasswordVisualTransformation() else VisualTransformation.None,
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
        trailingIcon = {
            IconButton(onClick = { passwordHidden = !passwordHidden }) {
                val visibilityIcon =
                    if (passwordHidden) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
                // Please provide localized description for accessibility services
                val description = if (passwordHidden) "Show password" else "Hide password"
                Icon(imageVector = visibilityIcon, contentDescription = description)
            }
        }
    )
}

TextFieldWithHideKeyboardOnImeAction

@Composable
@Sampled
@OptIn(ExperimentalComposeUiApi::class
fun TextFieldWithHideKeyboardOnImeAction() {
    val keyboardController = LocalSoftwareKeyboardController.current
    var text by rememberSaveable { mutableStateOf("") }
    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
        keyboardActions = KeyboardActions(
            onDone = {
                keyboardController?.hide()
                // do something here
            }
        )
    )
}

TextFieldSample

@Composable
@Sampled
fun TextFieldSample() {
    var text by rememberSaveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue("example", TextRange(0, 7)))
    }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}