The Compose Text team is completely rethinking the text field APIs from scratch. Come learn why, how we're approaching the process, and get a sneak peak at what the future might look like.
State management class ViewModel { val text = MutableStateFlow("") fun onTextUpdated(text: String) { // suspending call if (validate(text)) { text.value = text } } }
User study early validation – diverse backgrounds – interviews + take-home project – more info in previous talk: – bit.ly/3LnNqrI sign up: – goo.gle/AndroidDevUX
BasicTextField v2 var text by remember { mutableStateOf("") } BasicTextField( text, onValueChanged = { text = it } ) becomes var text by remember { mutableStateOf("") } BasicTextField( text, onValueChanged = { text = it } )
BasicTextField v2 var text by remember { mutableStateOf("") } BasicTextField( text, onValueChanged = { text = it } ) becomes val state: TextFieldState = rememberTextFieldState("") BasicTextField(state)
Reading text var text by remember { mutableStateOf("") } … Text("Hello $text!") becomes val state = rememberTextFieldState("") … Text("Hello ${state.text}!")
State hoisting …becomes class ViewModel { val textState = TextFieldState("") } @Composable fun Screen(viewModel: ViewModel) { TextField(viewModel.textState) }
Observing changes currently class ViewModel { private var textState by mutableStateOf("") suspend fun run() { snapshotFlow { textState } .collectLatest { processText(it) } } }
Setting text class ViewModel { private var textState by mutableStateOf("") fun prefill(text: String) { textState = prefill } } becomes class ViewModel { val textState = TextFieldState("") fun prefill(text: String) { textState.setTextAndPlaceCursorAtEnd(text) } }
TextFieldBuffer aka “StringBuilder with selection” class TextFieldBuffer: Appendable { val length: Int val selection: TextRange fun append(text: CharSequence?) fun replace(start: Int, end: Int, text: CharSequence) fun insert(index: Int, text: CharSequence) fun delete(start: Int, end: Int) fun replace(regex: Regex, text: CharSequence) fun setSelection(range: TextRange) fun placeCursorBeforeCharAt(offset: Int) // lots more to come… }
InputTransformation definition fun interface InputTransformation { val keyboardOptions: KeyboardOptions? get() = null fun TextFieldBuffer.transformInput() }
Visual transformations currently fun interface VisualTransformation { fun filter(text: AnnotatedString): TransformedText } class TransformedText( val text: AnnotatedString, val offsetMapping: OffsetMapping ) interface OffsetMapping { fun originalToTransformed(offset: Int): Int fun transformedToOriginal(offset: Int): Int }
Passwords …becomes BasicSecureTextField(state) Obfuscated text (customizable) – No cut/copy/drag (paste allowed) – IME password mode – Autofill support (planned) –