The editable text state of a text field, including both the [text] itself and position of the cursor or selection.
BasicTextFieldStateCompleteSample
fun BasicTextFieldStateCompleteSample() {
class SearchViewModel(val searchFieldState: TextFieldState = TextFieldState()) {
private val queryValidationRegex = """\w+""".toRegex()
// Use derived state to avoid recomposing every time the text changes, and only recompose
// when the input becomes valid or invalid.
val isQueryValid by derivedStateOf {
// This lambda will be re-executed every time inputState.text changes.
searchFieldState.text.matches(queryValidationRegex)
}
var searchResults: List<String> by mutableStateOf(emptyList())
private set
/** Called while the view model is active, e.g. from a LaunchedEffect. */
suspend fun run() {
snapshotFlow { searchFieldState.text }
.collectLatest { queryText ->
// Start a new search every time the user types something valid. If the previous
// search is still being processed when the text is changed, it will be
// cancelled
// and this code will run again with the latest query text.
if (isQueryValid) {
searchResults = performSearch(query = queryText)
}
}
}
fun clearQuery() {
searchFieldState.setTextAndPlaceCursorAtEnd("")
}
private suspend fun performSearch(query: CharSequence): List<String> {
TODO()
}
}
@Composable
fun SearchScreen(viewModel: SearchViewModel) {
Column {
Row {
BasicTextField(viewModel.searchFieldState)
IconButton(onClick = { viewModel.clearQuery() }) {
Icon(Icons.Default.Clear, contentDescription = "clear search query")
}
}
if (!viewModel.isQueryValid) {
Text("Invalid query", style = TextStyle(color = Color.Red))
}
LazyColumn { items(viewModel.searchResults) { TODO() } }
}
}
}