EditText to TextField

The main way for inputting text through user input in Compose is via TextField. As opposed to the EditText, this composable does not hold a reference to the value it renders. Instead it accepts the value it needs to display as a parameter. Similarly, is accepts a callback for when the text changes.

Both TextField and its variant OutlinedTextField support all stylistic options that appear on Google's Material Guidelines. This includes hints, outlines, leading and trailing icons.

A third variant of EditText also exists, called BasicTextField. This composable can be used for text input without any stylistic options. This is useful in cases you need additional customization freedom in your text input.

How to listen to text changes (TextChangedListener)

The TextField composable requires the text to render via the text parameter.

Once new text is input from the keyboard, the onTextChange is called with the updated value. You can then use the updated value to update the composable:

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = {
        // new text has been input
        text = it
    }
)

Normally, you would keep that value within a ViewModel. Once the new value is received you will forward the value back to the ViewModel, similarly to how you would normally do it using Views.

In the above example, the text is stored as a MutableState within the composable for simplicity.

How to change the text style of an TextField (text colors, fonts, etc)

Similar to Text a TextField accepts a textStyle which is used to customize the looks of the displayed text.

var text by remember { mutableStateOf("") }

TextField(
    textStyle = TextStyle(
        fontFamily = FontFamily.Monospace
    ),
    value = text,
    onValueChange = {
        text = it
    }
)

The above sample causes the TextField to render its text using the Monospace font.

How to specify the input type (phone numbers, e-mails, text, digits)

You can specify the expected input type of the TextField via the keyboardOptions parameter. This will request the selected soft-keyboard to display the best keyboard layout for the job.

The following example asks the soft-keyboard for a dial-pad layout, which will prompt the soft-keyboard to display a dial-pad layout.

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = {
        text = it
    },
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Phone
    )
)

How to specify and handle IME action (change ENTER to Done, Search, Next, etc)

The keyboardOptions parameter accepts an ImeAction. Depending on the value you provide, the soft-keyboard will display a different action instead of the return key.

By default, the return key will do nothing once pressed.

You can receive callbacks regarding keyboard actions via the keyboardActions parameter. You can specify actions for different events (such as onDone, onNext, onSearch, etc). Unless you need to handle a complicated scenario, the KeyboardActions provide an onAny callback.

var address by remember { mutableStateOf("") }

TextField(
    value = address,
    onValueChange = {
        address = it
    },
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Email,
        imeAction = ImeAction.Search
    )
)

How to listen to specific key press events

Use the onKeyEvent modifier to observe specific key press events. It works similarly to Views.setOnKeyListener(). It provides a KeyEvent with information about the key that was pressed (or released).

var text by remember { mutableStateOf("") }

TextField(
    modifier = Modifier.onKeyEvent { keyEvent ->
        if (keyEvent.type == KeyEventType.KeyUp
            && keyEvent.key == Key.Backspace
        ) {
            // Backspace was pressed.
            // consume the event by returning 'true'
            true
        } else {
            false
        }
    },
    value = text,
    onValueChange = {
        text = it
    }
)

How to request focus

The TextField composables will not request focus by default as opposed to EditText.

You need a reference to a FocusRequester() which provides the API for capturing focus. It is up to you to request focus when needed.

The following snippet tries to replicate the EditText's automatic way of receiving focus. The difference is that the focus will be requested only the first time the composable enters composition.

val focusRequester = remember { FocusRequester() }

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}
var value by remember { mutableStateOf("") }
TextField(
    modifier = Modifier.focusRequester(focusRequester),
    value = value,
    onValueChange = {
        value = it
    },
    keyboardOptions = KeyboardOptions(
        imeAction = ImeAction.Done
    ),
)

How to control keyboard focus

The FocusManager is the main API for controlling the direction of focus. You gain access to the API by using the respective composition local and controlling the focus on the appropriate callback.

The following sample showcases how to move focus from a first TextField to the second when the IME action is pressed. The last TextField will clear focus when the IME action is pressed.

Column {
    val focusManager = LocalFocusManager.current
    var value by remember { mutableStateOf("") }

    TextField(
        value = value,
        onValueChange = {
            value = it
        },
        singleLine = true,
        keyboardActions = KeyboardActions {
            focusManager.moveFocus(FocusDirection.Next)
        },
    )
    TextField(
        value = value,
        onValueChange = {
            value = it
        },
        singleLine = true,
        keyboardActions = KeyboardActions {
            focusManager.clearFocus(force = true)
        },
    )
}

How to show the soft-keyboard

The soft-keyboard will be automatically show as soon as a TextField is focused. Check how to request focus for a code sample.

How to hide the soft-keyboard

The soft-keyboard will be automatically dismissed when focus is cleared. The following sample clears focus when the IME action is pressed:

val focusManager = LocalFocusManager.current
var value by remember { mutableStateOf("") }

TextField(
    value = value,
    onValueChange = {
        value = it
    },
    singleLine = true,
    keyboardActions = KeyboardActions {
        focusManager.clearFocus(force = true)
    },
)

How to customize the style of your TextField (border, colors, etc)

You can modify the shape of your TextField by using the shape parameter. For example passing a RoundedCornerShape(20.dp) will render a TextField with rounded corners with a radius of 20 dp.

The colors of the TextField are controlled by the color parameter. It allows you to specify colors of very particular parts of your TextField such as its contents, background or cursor color. To make this easier, you can use the TextFieldDefaults functions for the default colors of the respective TextField.

var value by remember { mutableStateOf("") }

OutlinedTextField(
    shape = CircleShape,
    colors = TextFieldDefaults.textFieldColors(
        backgroundColor = 
                    MaterialTheme.colors.primary.copy(alpha = 0.12f),
    ),
    value = value,
    onValueChange = {
        value = it
    },
)

When styling your composables, prefer using colors via the current theme. You can gain access to the colors of your theme by using the MaterialTheme.colors object.

How to change colors of your TextField

Use the colors parameter to specify colors such as the text color, cursor color, error color and more.

Use the functions of the TextFieldDefaults object for default values:

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = {
        text = it
    },
    colors = TextFieldDefaults.textFieldColors(
        cursorColor = Color.Magenta,
        trailingIconColor = Color.LightGray,
        backgroundColor = Color.Transparent
    ),
    trailingIcon = {
        Icon(Icons.Rounded.Info, contentDescription = null)
    }
)

How to display an error to your TextField

Pass true to the isError parameter to signify that the TextField is in error state. This will make the trailing icon, label and bottom indicator to be tinted in the error color:

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = {
        text = it
    },
    isError = text.isEmpty(),
    trailingIcon = {
        Icon(Icons.Rounded.Edit, contentDescription = null)
    }
)

Am I forced to use the Material Guidelines looks for my InputText

If TextField and OutlinedTextField might not fit the style of your application's design, you can use BasicTextField to match your preferred looks.

Previous ChapterTextView to Text
Next ChapterDisplaying Images & Photos