BasicTextField
は Jetpack Compose 1.7.0 のタイミングで BasicTextField2
からリネームされて新しいものに切り替わりました。
その新しくなった BasicTextField
で入力内容の Undo/Redo の API が追加されています。
その Undo/Redo 機能の紹介です。
material の TextField
と OutlinedTextField
は compose-material 1.7.7 or compose-material3 1.3.3 時点では TextFieldState
を直接操作しない形になっているため、現時点では BasicTextField
のみでの使用が可能となっています。
使い方
TextFieldState
から UndoState
を使って操作します。
val textFieldState = rememberTextFieldState()
Column {
BasicTextField(
state = textFieldState,
modifier = Modifier.weight(1f)
)
Row {
Button(
onClick = {
state.undoState.undo()
},
enabled = state.undoState.canUndo
) {
Text("Undo")
}
Button(
onClick = {
state.undoState.redo()
},
enabled = state.undoState.canRedo
) {
Text("Redo")
}
}
}
できること
-
BasicTextField
に対して入力された内容の Undo/Redo - 残せる履歴は 100 件まで
- 履歴のクリアはできるが、一覧の取得はできない
- 物理キーボードでの Undo/Redo のショートカットに対応している
入力時の挙動例
共通の挙動
- 最後に入力してから 5000ms 以上経過した地点までを入力中であっても履歴に追加する
- 改行は履歴に追加する
Gboard の日本語入力の場合
- 基本的には入力した内容が履歴に追加されるが、履歴に追加されるタイミングが難しい
- フリック入力ではなく連打して入力された文字は全て履歴に残る
- "お("あ"のキーを連打して入力)" - 確定 -> ["あ", "い", "う", "え", "お"]
- 小書きや濁音半濁音に変換された地点までの入力が履歴に追加される
- "やばい" - 確定 -> ["やは", "やば", "やばい"]
- 入力中に対してキーボードの "変換" が押下されると表示が切り替わった分だけ履歴に追加される
- "きょう" - 変換 - "今日" - 変換 - "2025/02/07" - 確定 -> ["きよ", "きょう", "今日", "2025/02/07"]
- 入力中のテキストに対して候補から選択したときは入力中のものと候補から選択したものの両方が履歴に追加される
- "あした" - 候補から選択 - "2025/02/08" -> ["あした", "2025/02/08"]
Gboard の英語入力の場合
- 日本語に比べると変換パターンが少なく癖なく履歴に追加される
- スペースが入力されるまでをひとまとまりで履歴に追加する
- "tomorrow" - スペース -> ["tomorrow "]
- 入力中のテキストに対して候補から選択したときは候補から選択したものが一つの履歴に追加される
- "to" - 候補から選択 - "tomorrow " -> ["tomorrow "]
- なぞり入力の場合はなぞりで入力したものが履歴に追加され、なぞり入力後に候補から選択した時にはそれぞれが履歴に追加される
- "help(なぞりで)" - 候補から選択 - "hey " -> ["help", "hey "]
実装
この辺りがその実装になっています。
手動でのテキスト操作時の挙動
以下のように BasicTextField
ではコードからもテキストの操作ができます。
textFieldState.edit {
insert(5, "inserted text")
delete(12, 13)
append("appended text")
replace(0, 5, "replaced text")
}
テキストの操作はできますが、これらの操作は履歴に追加されません。
ユーザの操作のみが履歴に追加されます。