androidx.compose.foundation.text
In this page, you'll find documentation for types, properties, and functions available in the androidx.compose.foundation.text package such as BasicText, BasicTextFiled, KeyboardActions, and KeyboardOptions.
If you're looking for guidance instead, check out the Text in Compose guide.
Interfaces
KeyboardActionScope |
This scope can be used to execute the default action implementation. |
Cmn
|
TextAutoSize |
Interface used by Text composables to override text size to automatically grow or shrink text to fill the layout bounds. |
Cmn
|
Classes
InlineTextContent |
A data class that stores a composable to be inserted into the text layout. |
Cmn
|
KeyboardActions |
The |
Cmn
|
KeyboardOptions |
The keyboard configuration options for TextFields. |
Cmn
|
Objects
TextAutoSizeDefaults |
Contains defaults for |
Cmn
|
Annotations
Top-level functions summary
Unit |
@ComposableBasicSecureTextField is specifically designed for password entry fields and is a preconfigured alternative to |
Cmn
|
Unit |
@ComposableBasic element that displays text and provides semantics / accessibility information. |
Cmn
|
Unit |
@ComposableBasic element that displays text and provides semantics / accessibility information. |
Cmn
|
Unit |
@ComposableBasic text composable that provides an interactive box that accepts text input through software or hardware keyboard, but provides no decorations like hint or placeholder. |
Cmn
|
Unit |
@ComposableBasic composable that enables users to edit text via hardware or software keyboard, but provides no decorations like hint or placeholder. |
Cmn
|
Unit |
@ComposableBasic composable that enables users to edit text via hardware or software keyboard, but provides no decorations like hint or placeholder. |
Cmn
|
Unit |
@ComposableThis function is deprecated. Use Text or BasicText and pass an AnnotatedString that contains a LinkAnnotation. |
Cmn
|
KeyboardActions |
KeyboardActions(onAny: KeyboardActionScope.() -> Unit)Creates an instance of |
Cmn
|
Extension functions summary
Unit |
AnnotatedString.Builder.appendInlineContent(Used to insert composables into the text layout. |
Cmn
|
Top-level properties summary
ProvidableCompositionLocal<Brush> |
CompositionLocal used to change the highlight |
Cmn
|
ProvidableCompositionLocal<Color> |
This property is deprecated. Use LocalAutofillHighlightBrush instead. |
Cmn
|
ProvidableCompositionLocal<Executor?> |
CompositionLocal that provides an Executor for background text processing to potentially get run on. |
android
|
Top-level functions
BasicSecureTextField
@Composable
fun BasicSecureTextField(
state: TextFieldState,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
inputTransformation: InputTransformation? = null,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.SecureTextField,
onKeyboardAction: KeyboardActionHandler? = null,
onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
cursorBrush: Brush = SolidColor(Color.Black),
decorator: TextFieldDecorator? = null,
textObfuscationMode: TextObfuscationMode = TextObfuscationMode.Default,
textObfuscationCharacter: Char = DefaultObfuscationCharacter,
scrollState: ScrollState = rememberScrollState()
): Unit
BasicSecureTextField is specifically designed for password entry fields and is a preconfigured alternative to BasicTextField. It only supports a single line of content and comes with default settings for KeyboardOptions, InputTransformation, and CodepointTransformation that are appropriate for entering secure content. Additionally, some context menu actions like cut, copy, and drag are disabled for added security.
| Parameters | |
|---|---|
state: TextFieldState |
|
modifier: Modifier = Modifier |
optional |
enabled: Boolean = true |
controls the enabled state of the |
readOnly: Boolean = false |
controls the editable state of the |
inputTransformation: InputTransformation? = null |
Optional |
textStyle: TextStyle = TextStyle.Default |
Style configuration for text content that's displayed in the editor. |
keyboardOptions: KeyboardOptions = KeyboardOptions.SecureTextField |
Software keyboard options that contain configurations such as |
onKeyboardAction: KeyboardActionHandler? = null |
Called when the user presses the action button in the input method editor (IME), or by pressing the enter key on a hardware keyboard. By default this parameter is null, and would execute the default behavior for a received IME Action e.g., |
onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null |
Callback that is executed when the text layout becomes queryable. The callback receives a function that returns a |
interactionSource: MutableInteractionSource? = null |
the |
cursorBrush: Brush = SolidColor(Color.Black) |
|
decorator: TextFieldDecorator? = null |
Allows to add decorations around text field, such as icon, placeholder, helper messages or similar, and automatically increase the hit target area of the text field. |
textObfuscationMode: TextObfuscationMode = TextObfuscationMode.Default |
Determines the method used to obscure the input text. |
textObfuscationCharacter: Char = DefaultObfuscationCharacter |
Which character to use while obfuscating the text. It doesn't have an effect when |
scrollState: ScrollState = rememberScrollState() |
The scroll state of the text field. Since |
BasicText
@Composable
fun BasicText(
text: String,
modifier: Modifier = Modifier,
style: TextStyle = TextStyle.Default,
onTextLayout: ((TextLayoutResult) -> Unit)? = null,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
minLines: Int = 1,
color: ColorProducer? = null,
autoSize: TextAutoSize? = null
): Unit
Basic element that displays text and provides semantics / accessibility information. Typically you will instead want to use androidx.compose.material.Text, which is a higher level Text element that contains semantics and consumes style information from a theme.
| Parameters | |
|---|---|
text: String |
The text to be displayed. |
modifier: Modifier = Modifier |
|
style: TextStyle = TextStyle.Default |
Style configuration for the text such as color, font, line height etc. |
onTextLayout: ((TextLayoutResult) -> Unit)? = null |
Callback that is executed when a new text layout is calculated. A |
overflow: TextOverflow = TextOverflow.Clip |
How visual overflow should be handled. |
softWrap: Boolean = true |
Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If |
maxLines: Int = Int.MAX_VALUE |
An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to |
minLines: Int = 1 |
The minimum height in terms of minimum number of visible lines. It is required that 1 <= |
color: ColorProducer? = null |
Overrides the text color provided in |
autoSize: TextAutoSize? = null |
Enable auto sizing for this text composable. Finds the biggest font size that fits in the available space and lays the text out with this size. This performs multiple layout passes and can be slower than using a fixed font size. This takes precedence over sizes defined through |
BasicText
@Composable
fun BasicText(
text: AnnotatedString,
modifier: Modifier = Modifier,
style: TextStyle = TextStyle.Default,
onTextLayout: ((TextLayoutResult) -> Unit)? = null,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
minLines: Int = 1,
inlineContent: Map<String, InlineTextContent> = mapOf(),
color: ColorProducer? = null,
autoSize: TextAutoSize? = null
): Unit
Basic element that displays text and provides semantics / accessibility information. Typically you will instead want to use androidx.compose.material.Text, which is a higher level Text element that contains semantics and consumes style information from a theme.
| Parameters | |
|---|---|
text: AnnotatedString |
The text to be displayed. |
modifier: Modifier = Modifier |
|
style: TextStyle = TextStyle.Default |
Style configuration for the text such as color, font, line height etc. |
onTextLayout: ((TextLayoutResult) -> Unit)? = null |
Callback that is executed when a new text layout is calculated. A |
overflow: TextOverflow = TextOverflow.Clip |
How visual overflow should be handled. |
softWrap: Boolean = true |
Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If |
maxLines: Int = Int.MAX_VALUE |
An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to |
minLines: Int = 1 |
The minimum height in terms of minimum number of visible lines. It is required that 1 <= |
inlineContent: Map<String, InlineTextContent> = mapOf() |
A map store composables that replaces certain ranges of the text. It's used to insert composables into text layout. Check |
color: ColorProducer? = null |
Overrides the text color provided in |
autoSize: TextAutoSize? = null |
Enable auto sizing for this text composable. Finds the biggest font size that fits in the available space and lays the text out with this size. This performs multiple layout passes and can be slower than using a fixed font size. This takes precedence over sizes defined through |
BasicTextField
@Composable
fun BasicTextField(
state: TextFieldState,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
inputTransformation: InputTransformation? = null,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
onKeyboardAction: KeyboardActionHandler? = null,
lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default,
onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
cursorBrush: Brush = BasicTextFieldDefaults.CursorBrush,
outputTransformation: OutputTransformation? = null,
decorator: TextFieldDecorator? = null,
scrollState: ScrollState = rememberScrollState()
): Unit
Basic text composable that provides an interactive box that accepts text input through software or hardware keyboard, but provides no decorations like hint or placeholder.
All the editing state of this composable is hoisted through state. Whenever the contents of this composable change via user input or semantics, TextFieldState.text gets updated. Similarly, all the programmatic updates made to state also reflect on this composable.
If you want to add decorations to your text field, such as icon or similar, and increase the hit target area, use the decorator.
In order to filter (e.g. only allow digits, limit the number of characters), or change (e.g. convert every character to uppercase) the input received from the user, use an InputTransformation.
Limiting the height of the BasicTextField in terms of line count and choosing a scroll direction can be achieved by using TextFieldLineLimits.
Scroll state of the composable is also hoisted to enable observation and manipulation of the scroll behavior by the developer, e.g. bringing a searched keyword into view by scrolling to its position without focusing, or changing selection.
It's also possible to internally wrap around an existing TextFieldState and expose a more lightweight state hoisting mechanism through a value that dictates the content of the TextField and an onValueChange callback that communicates the changes to this value.
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MailOutline import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp // Demonstrates how to use the decorator API on BasicTextField val state = rememberTextFieldState("Hello, World!") BasicTextField( state = state, decorator = { innerTextField -> // Because the decorator is used, the whole Row gets the same behaviour as the internal // input field would have otherwise. For example, there is no need to add a // `Modifier.clickable` to the Row anymore to bring the text field into focus when user // taps on a larger text field area which includes paddings and the icon areas. Row( Modifier.background(Color.LightGray, RoundedCornerShape(percent = 30)) .padding(16.dp) ) { Icon(Icons.Default.MailOutline, contentDescription = "Mail Icon") Spacer(Modifier.width(16.dp)) innerTextField() } }, )
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.input.InputTransformation import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.delete import androidx.compose.foundation.text.input.insert import androidx.compose.material.Text import androidx.compose.runtime.remember // Demonstrates how to create a custom and relatively complex InputTransformation. val state = remember { TextFieldState() } BasicTextField( state, inputTransformation = InputTransformation { // A filter that always places newly-input text at the start of the string, after a // prompt character, like a shell. val promptChar = '>' fun CharSequence.countPrefix(char: Char): Int { var i = 0 while (i < length && get(i) == char) i++ return i } // Step one: Figure out the insertion point. val newPromptChars = asCharSequence().countPrefix(promptChar) val insertionPoint = if (newPromptChars == 0) 0 else 1 // Step two: Ensure text is placed at the insertion point. if (changes.changeCount == 1) { val insertedRange = changes.getRange(0) val replacedRange = changes.getOriginalRange(0) if (!replacedRange.collapsed && insertedRange.collapsed) { // Text was deleted, delete forwards from insertion point. delete(insertionPoint, insertionPoint + replacedRange.length) } } // Else text was replaced or there were multiple changes - don't handle. // Step three: Ensure the prompt character is there. if (newPromptChars == 0) { insert(0, ">") } // Step four: Ensure the cursor is ready for the next input. placeCursorAfterCharAt(0) }, )
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember var text by remember { mutableStateOf("") } // A reference implementation that demonstrates how to create a TextField with the legacy // state hoisting design around `BasicTextField(TextFieldState)` StringTextField(value = text, onValueChange = { text = it })
| Parameters | |
|---|---|
state: TextFieldState |
|
modifier: Modifier = Modifier |
optional |
enabled: Boolean = true |
controls the enabled state of the |
readOnly: Boolean = false |
controls the editable state of the |
inputTransformation: InputTransformation? = null |
Optional |
textStyle: TextStyle = TextStyle.Default |
Typographic and graphic style configuration for text content that's displayed in the editor. |
keyboardOptions: KeyboardOptions = KeyboardOptions.Default |
Software keyboard options that contain configurations such as |
onKeyboardAction: KeyboardActionHandler? = null |
Called when the user presses the action button in the input method editor (IME), or by pressing the enter key on a hardware keyboard if the |
lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default |
Whether the text field should be |
onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null |
Callback that is executed when the text layout becomes queryable. The callback receives a function that returns a |
interactionSource: MutableInteractionSource? = null |
the |
cursorBrush: Brush = BasicTextFieldDefaults.CursorBrush |
|
outputTransformation: OutputTransformation? = null |
An |
decorator: TextFieldDecorator? = null |
Allows to add decorations around text field, such as icon, placeholder, helper messages or similar, and automatically increase the hit target area of the text field. |
scrollState: ScrollState = rememberScrollState() |
Scroll state that manages either horizontal or vertical scroll of TextField. If |
BasicTextField
@Composable
fun BasicTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
minLines: Int = 1,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource? = null,
cursorBrush: Brush = SolidColor(Color.Black),
decorationBox: @Composable (@Composable innerTextField: () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() }
): Unit
Basic composable that enables users to edit text via hardware or software keyboard, but provides no decorations like hint or placeholder.
Whenever the user edits the text, onValueChange is called with the most up to date state represented by String with which developer is expected to update their state.
Unlike TextFieldValue overload, this composable does not let the developer control selection, cursor and text composition information. Please check TextFieldValue and corresponding BasicTextField overload for more information.
It is crucial that the value provided to the onValueChange is fed back into BasicTextField in order to actually display and continue to edit that text in the field. The value you feed back into the field may be different than the one provided to the onValueChange callback, however the following caveats apply:
-
The new value must be provided to
BasicTextFieldimmediately (i.e. by the next frame), or the text field may appear to glitch, e.g. the cursor may jump around. For more information about this requirement, see this article. -
The value fed back into the field may be different from the one passed to
onValueChange, although this may result in the input connection being restarted, which can make the keyboard flicker for the user. This is acceptable when you're using the callback to, for example, filter out certain types of input, but should probably not be done on every update when entering freeform text.
This composable provides basic text editing functionality, however does not include any decorations such as borders, hints/placeholder. A design system based implementation such as Material Design Filled text field is typically what is needed to cover most of the needs. This composable is designed to be used when a custom implementation for different design system is needed.
Example usage:
import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable var value by rememberSaveable { mutableStateOf("initial value") } BasicTextField( value = value, onValueChange = { // it is crucial that the update is fed back into BasicTextField in order to // see updates on the text value = it }, )
For example, if you need to include a placeholder in your TextField, you can write a composable using the decoration box like this:
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable var value by rememberSaveable { mutableStateOf("initial value") } Box { BasicTextField(value = value, onValueChange = { value = it }) if (value.isEmpty()) { Text(text = "Placeholder") } }
If you want to add decorations to your text field, such as icon or similar, and increase the hit target area, use the decoration box:
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MailOutline import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp var value by rememberSaveable { mutableStateOf("initial value") } BasicTextField( value = value, onValueChange = { value = it }, decorationBox = { innerTextField -> // Because the decorationBox is used, the whole Row gets the same behaviour as the // internal input field would have otherwise. For example, there is no need to add a // Modifier.clickable to the Row anymore to bring the text field into focus when user // taps on a larger text field area which includes paddings and the icon areas. Row( Modifier.background(Color.LightGray, RoundedCornerShape(percent = 30)) .padding(16.dp) ) { Icon(Icons.Default.MailOutline, contentDescription = null) Spacer(Modifier.width(16.dp)) innerTextField() } }, )
In order to create formatted text field, for example for entering a phone number or a social security number, use a visualTransformation parameter. Below is the example of the text field for entering a credit card number:
import androidx.compose.foundation.background import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.OffsetMapping import androidx.compose.ui.text.input.TransformedText import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.substring import androidx.compose.ui.unit.dp /** The offset translator used for credit card input field */ val creditCardOffsetTranslator = object : OffsetMapping { override fun originalToTransformed(offset: Int): Int { return when { offset < 4 -> offset offset < 8 -> offset + 1 offset < 12 -> offset + 2 offset <= 16 -> offset + 3 else -> 19 } } override fun transformedToOriginal(offset: Int): Int { return when { offset <= 4 -> offset offset <= 9 -> offset - 1 offset <= 14 -> offset - 2 offset <= 19 -> offset - 3 else -> 16 } } } /** * Converts up to 16 digits to hyphen connected 4 digits string. For example, "1234567890123456" * will be shown as "1234-5678-9012-3456" */ val creditCardTransformation = VisualTransformation { text -> val trimmedText = if (text.text.length > 16) text.text.substring(0..15) else text.text var transformedText = "" trimmedText.forEachIndexed { index, char -> transformedText += char if ((index + 1) % 4 == 0 && index != 15) transformedText += "-" } TransformedText(AnnotatedString(transformedText), creditCardOffsetTranslator) } var text by rememberSaveable { mutableStateOf("") } BasicTextField( value = text, onValueChange = { input -> if (input.length <= 16 && input.none { !it.isDigit() }) { text = input } }, modifier = Modifier.size(170.dp, 30.dp).background(Color.LightGray).wrapContentSize(), singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), visualTransformation = creditCardTransformation, )
Note: This overload does not support KeyboardOptions.showKeyboardOnFocus.
| Parameters | |
|---|---|
value: String |
the input |
onValueChange: (String) -> Unit |
the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback |
modifier: Modifier = Modifier |
optional |
enabled: Boolean = true |
controls the enabled state of the |
readOnly: Boolean = false |
controls the editable state of the |
textStyle: TextStyle = TextStyle.Default |
Style configuration that applies at character level such as color, font etc. |
keyboardOptions: KeyboardOptions = KeyboardOptions.Default |
software keyboard options that contains configuration such as |
keyboardActions: KeyboardActions = KeyboardActions.Default |
when 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 |
singleLine: Boolean = false |
when 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 |
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE |
the maximum height in terms of maximum number of visible lines. It is required that 1 <= |
minLines: Int = 1 |
the minimum height in terms of minimum number of visible lines. It is required that 1 <= |
visualTransformation: VisualTransformation = VisualTransformation.None |
The visual transformation filter for changing the visual representation of the input. By default no visual transformation is applied. |
onTextLayout: (TextLayoutResult) -> Unit = {} |
Callback that is executed when a new text layout is calculated. A |
interactionSource: MutableInteractionSource? = null |
an optional hoisted |
cursorBrush: Brush = SolidColor(Color.Black) |
|
decorationBox: @Composable (@Composable innerTextField: () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() } |
Composable lambda that allows to add decorations around text field, such as icon, placeholder, helper messages or similar, and automatically increase the hit target area of the text field. To allow you to control the placement of the inner text field relative to your decorations, the text field implementation will pass in a framework-controlled composable parameter "innerTextField" to the decorationBox lambda you provide. You must call innerTextField exactly once. |
BasicTextField
@Composable
fun BasicTextField(
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
minLines: Int = 1,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource? = null,
cursorBrush: Brush = SolidColor(Color.Black),
decorationBox: @Composable (@Composable innerTextField: () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() }
): Unit
Basic composable that enables users to edit text via hardware or software keyboard, but provides no decorations like hint or placeholder.
Whenever the user edits the text, onValueChange is called with the most up to date state represented by TextFieldValue. TextFieldValue contains the text entered by user, as well as selection, cursor and text composition information. Please check TextFieldValue for the description of its contents.
It is crucial that the value provided to the onValueChange is fed back into BasicTextField in order to actually display and continue to edit that text in the field. The value you feed back into the field may be different than the one provided to the onValueChange callback, however the following caveats apply:
-
The new value must be provided to
BasicTextFieldimmediately (i.e. by the next frame), or the text field may appear to glitch, e.g. the cursor may jump around. For more information about this requirement, see this article. -
The value fed back into the field may be different from the one passed to
onValueChange, although this may result in the input connection being restarted, which can make the keyboard flicker for the user. This is acceptable when you're using the callback to, for example, filter out certain types of input, but should probably not be done on every update when entering freeform text.
This composable provides basic text editing functionality, however does not include any decorations such as borders, hints/placeholder. A design system based implementation such as Material Design Filled text field is typically what is needed to cover most of the needs. This composable is designed to be used when a custom implementation for different design system is needed.
Example usage:
import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.text.input.TextFieldValue var value by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue()) } BasicTextField( value = value, onValueChange = { // it is crucial that the update is fed back into BasicTextField in order to // see updates on the text value = it }, )
For example, if you need to include a placeholder in your TextField, you can write a composable using the decoration box like this:
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable var value by rememberSaveable { mutableStateOf("initial value") } Box { BasicTextField(value = value, onValueChange = { value = it }) if (value.isEmpty()) { Text(text = "Placeholder") } }
If you want to add decorations to your text field, such as icon or similar, and increase the hit target area, use the decoration box:
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MailOutline import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp var value by rememberSaveable { mutableStateOf("initial value") } BasicTextField( value = value, onValueChange = { value = it }, decorationBox = { innerTextField -> // Because the decorationBox is used, the whole Row gets the same behaviour as the // internal input field would have otherwise. For example, there is no need to add a // Modifier.clickable to the Row anymore to bring the text field into focus when user // taps on a larger text field area which includes paddings and the icon areas. Row( Modifier.background(Color.LightGray, RoundedCornerShape(percent = 30)) .padding(16.dp) ) { Icon(Icons.Default.MailOutline, contentDescription = null) Spacer(Modifier.width(16.dp)) innerTextField() } }, )
Note: This overload does not support KeyboardOptions.showKeyboardOnFocus.
| Parameters | |
|---|---|
value: TextFieldValue |
The |
onValueChange: (TextFieldValue) -> Unit |
Called when the input service updates the values in |
modifier: Modifier = Modifier |
optional |
enabled: Boolean = true |
controls the enabled state of the |
readOnly: Boolean = false |
controls the editable state of the |
textStyle: TextStyle = TextStyle.Default |
Style configuration that applies at character level such as color, font etc. |
keyboardOptions: KeyboardOptions = KeyboardOptions.Default |
software keyboard options that contains configuration such as |
keyboardActions: KeyboardActions = KeyboardActions.Default |
when 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 |
singleLine: Boolean = false |
when 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 |
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE |
the maximum height in terms of maximum number of visible lines. It is required that 1 <= |
minLines: Int = 1 |
the minimum height in terms of minimum number of visible lines. It is required that 1 <= |
visualTransformation: VisualTransformation = VisualTransformation.None |
The visual transformation filter for changing the visual representation of the input. By default no visual transformation is applied. |
onTextLayout: (TextLayoutResult) -> Unit = {} |
Callback that is executed when a new text layout is calculated. A |
interactionSource: MutableInteractionSource? = null |
an optional hoisted |
cursorBrush: Brush = SolidColor(Color.Black) |
|
decorationBox: @Composable (@Composable innerTextField: () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() } |
Composable lambda that allows to add decorations around text field, such as icon, placeholder, helper messages or similar, and automatically increase the hit target area of the text field. To allow you to control the placement of the inner text field relative to your decorations, the text field implementation will pass in a framework-controlled composable parameter "innerTextField" to the decorationBox lambda you provide. You must call innerTextField exactly once. |
ClickableText
@Composable
funClickableText(
text: AnnotatedString,
modifier: Modifier = Modifier,
style: TextStyle = TextStyle.Default,
softWrap: Boolean = true,
overflow: TextOverflow = TextOverflow.Clip,
maxLines: Int = Int.MAX_VALUE,
onTextLayout: (TextLayoutResult) -> Unit = {},
onClick: (Int) -> Unit
): Unit
A continent version of BasicText component to be able to handle click event on the text.
This is a shorthand of BasicText with pointerInput to be able to handle click event easily.
import androidx.compose.foundation.text.ClickableText import androidx.compose.material.Text import androidx.compose.ui.text.AnnotatedString ClickableText( text = AnnotatedString("Click Me"), onClick = { offset -> Log.d("ClickableText", "$offset -th character is clicked.") }, )
For other gestures, e.g. long press, dragging, follow sample code.
import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.material.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.text.TextLayoutResult val layoutResult = remember { mutableStateOf<TextLayoutResult?>(null) } val gesture = Modifier.pointerInput(onLongClick) { detectTapGestures( onLongPress = { pos -> layoutResult.value?.let { layout -> onLongClick(layout.getOffsetForPosition(pos)) } } ) } Text( text = text, modifier = modifier.then(gesture), style = style, softWrap = softWrap, overflow = overflow, maxLines = maxLines, onTextLayout = { onTextLayout(it) layoutResult.value = it }, )
| Parameters | |
|---|---|
text: AnnotatedString |
The text to be displayed. |
modifier: Modifier = Modifier |
Modifier to apply to this layout node. |
style: TextStyle = TextStyle.Default |
Style configuration for the text such as color, font, line height etc. |
softWrap: Boolean = true |
Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If |
overflow: TextOverflow = TextOverflow.Clip |
How visual overflow should be handled. |
maxLines: Int = Int.MAX_VALUE |
An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to |
onTextLayout: (TextLayoutResult) -> Unit = {} |
Callback that is executed when a new text layout is calculated. A |
onClick: (Int) -> Unit |
Callback that is executed when users click the text. This callback is called with clicked character's offset. Note: this composable is now deprecated. Instead, use regular |
KeyboardActions
fun KeyboardActions(onAny: KeyboardActionScope.() -> Unit): KeyboardActions
Creates an instance of KeyboardActions that uses the specified lambda for all ImeActions.
Extension functions
appendInlineContent
fun AnnotatedString.Builder.appendInlineContent(
id: String,
alternateText: String = REPLACEMENT_CHAR
): Unit
Used to insert composables into the text layout. This method can be used together with the inlineContent parameter of BasicText. It will append the alternateText to this AnnotatedString and also mark this range of text to be replaced by a composable. BasicText will try to find an InlineTextContent in the map defined by inlineContent whose key equals to id, and it will use the InlineTextContent.children to replace this range of text.
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.InlineTextContent import androidx.compose.foundation.text.appendInlineContent import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.unit.em val myId = "inlineContent" val text = buildAnnotatedString { append("Hello") // Append a placeholder string "[myBox]" and attach an annotation "inlineContent" on it. appendInlineContent(myId, "[myBox]") } val inlineContent = mapOf( Pair( // This tells the [BasicText] to replace the placeholder string "[myBox]" by // the composable given in the [InlineTextContent] object. myId, InlineTextContent( // Placeholder tells text layout the expected size and vertical alignment of // children composable. Placeholder( width = 0.5.em, height = 0.5.em, placeholderVerticalAlign = PlaceholderVerticalAlign.AboveBaseline, ) ) { // This [Box] will fill maximum size, which is specified by the [Placeholder] // above. Notice the width and height in [Placeholder] are specified in // TextUnit, // and are converted into pixel by text layout. Box(modifier = Modifier.fillMaxSize().background(color = Color.Red)) }, ) ) BasicText(text = text, inlineContent = inlineContent)
| Parameters | |
|---|---|
id: String |
The id used to look up the |
alternateText: String = REPLACEMENT_CHAR |
The text to be replaced by the inline content. It's displayed when the inlineContent parameter of |
| Throws | |
|---|---|
kotlin.IllegalArgumentException |
if |
| See also | |
|---|---|
InlineTextContent |
|
BasicText |
Top-level properties
LocalAutofillHighlightBrush
val LocalAutofillHighlightBrush: ProvidableCompositionLocal<Brush>
CompositionLocal used to change the highlight Brush used for autofilled components.
LocalAutofillHighlightColor
val LocalAutofillHighlightColor: ProvidableCompositionLocal<Color>
CompositionLocal used to change the autofillHighlightColor used by components in the hierarchy.
LocalBackgroundTextMeasurementExecutor
val LocalBackgroundTextMeasurementExecutor: ProvidableCompositionLocal<Executor?>
CompositionLocal that provides an Executor for background text processing to potentially get run on.
BasicText premeasure is the process of using a background thread to early start metrics calculation for Text composables on Android to warm up the underlying text layout cache. This becomes especially useful in LazyLists when precomposition may precede premeasurement by at least a frame, which gives the background thread enough time to fully calculate text metrics. This approximately reduces text layout duration on main thread from 50% to 90%.
By default this CompositionLocal provides null, which means that any text prefetch behavior will revert to the system default. You can provide an executor like Executors.newSingleThreadExecutor() for BasicText to schedule background tasks.
Please note that prefetch text does not guarantee a net performance increase. It may actually be harmful in certain scenarios where there is not enough time between composition and measurement for background thread to actually start warming the cache, or when the text is long enough that it floods the cache and overflows it, at around 5000 words.
Use benchmarking tools to check whether enabling this behavior works well for your use case.
import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.LocalBackgroundTextMeasurementExecutor import androidx.compose.runtime.CompositionLocalProvider CompositionLocalProvider( LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor ) { BasicText("Hello World!") }