TextFieldValue
に代わる新しい TextFieldState
の使い方について解説します。 TextFieldState
は新しい BasicTextField
(以前は BasicTextField2
と呼ばれていたものです。 BasicTextField
にリネームされてます。)で使用されることになります。
TextFieldState
はCompose 1.7.0でStableになっています。
新しい BasicTextField
も使い方が結構変わってますが、今回は TextFieldState
のみに焦点を絞っています。
(気が向けば新しい BasicTextField
ついても何か書くかも?)
基本的な使い方
単純に入力欄を作る方法です。
// TextFieldStateの作成
val textFieldState = rememberTextFieldState("test")
BasicTextField(
state = textFieldState, // BasicTextFieldに渡す
decorator = { innerTextField ->
Box(
modifier = Modifier
.fillMaxWidth()
.border(width = 1.dp, color = Color.Black)
.padding(16.dp)
) {
innerTextField()
}
},
modifier = Modifier.fillMaxWidth()
)
rememberTextFieldState
を使ってまずは TextFieldState
を作成します。実装をみればすぐ分かりますが、 rememberSaveable
で囲ったものを作ってるだけです。引数は初期値になります。
あとはこれを BasicTextField
に渡すだけです。
これまでとの大きな違いとしては、 onValueChange
を使って入力欄を更新する必要がなく自動で反映されます。
ViewModelで状態を保持したい場合も特に難しくはなく、単純に以下のようにViewModelで保持しておくだけです。値の取得も text
で取得できます。
// ViewModel
class MainViewModel: ViewModel() {
val textFieldState = TextFieldState("test")
fun execute() {
// 入力された値を取得
val text = textFieldState.text
// ...
}
}
// Composable
BasicTextField(
state = viewModel.textFieldState,
// ...
)
入力の監視
入力状態を監視するには、 snapshotFlow
を使って text
を監視します。
LaunchedEffect(Unit) {
snapshotFlow { textFieldState.text }.collectLatest {
Log.d(TAG, "text = $it")
}
}
また、入力が特定の状態を満たすかどうかを確認する場合は、 derivedStateOf
を使うこともできます。
val isTest by remember {
derivedStateOf {
textFieldState.text == "test"
}
}
// "test"と入力された時だけtrueになる
テキストの編集
コードからテキストを編集する方法です。
まずは一番簡単例として、入力された値をクリアする方法です。 clearText
を使うだけです。
textFieldState.clearText()
次に全体のテキストを単純に置き換える方法です。これには2つ方法があり、違いとしては変更後のカーソルになります。
// テキストを置き換えて、すべて選択された状態にする
textFieldState.setTextAndSelectAll("Sample")
// テキストを置き換えて、末尾にカーソルを移動させる
textFieldState.setTextAndPlaceCursorAtEnd("Sample")
さらに柔軟にテキストを編集する場合は edit
を使います。上で紹介した編集方法はすべて edit
が呼び出されています。また、 selection
を使って選択状態を指定できます。
textFieldState.edit {
// 全部消す
delete(0, length)
// "Compose"を追加
append("Compose")
// "Hello, "を先頭に追加
insert(0, "Hello, ")
// "Compose"の部分を選択状態にする
selection = TextRange(7, length)
}
また、 placeCursorBeforeCharAt
, placeCursorAfterCharAt
, placeCursorAtEnd
を使うことでカーソル位置も指定することが可能です。
IME変換状態
日本語ではキーボードから入力されてから漢字等に変換してからテキストが確定しますが、この変換中かどうかを判定する方法です。こちらも snapshotFlow
を使い composition
を監視します。
LaunchedEffect(Unit) {
snapshotFlow { textFieldState.composition }.collectLatest {
// null => 変換中じゃない
// TextRange => 変換中の範囲
}
}
取得される値としては、変換中じゃない場合はnullになります。変換中のときは変換中の範囲が TextRange
として取得できます。