【JetpackCompose】 TextField の singleLine は物理キーボードの Enter には無力
無力というか、ぱっと見で Enter の挙動について勘違いしてしまうかな、というものです。
JetpackCompose の TextField
には singleLine
という引数があって、1行しか表示したくない時に利用されます。
var value by remember { mutableStateOf("") } TextField( value = value, onValueChange = { value = it }, singleLine = true )
この状態で、スマートフォンやタブレットにて、ソフトウェアキーボードを使っている時は特に問題なく1行に収まると思うのですが、物理キーボードを接続してEnter キーを押すと改行されてしまい、1行ではなくなってしまいます。
これは正確には、物理キーボード入力でなくとも、改行コードが入ってくると singleLine
が true でも改行されます。TextField
は改行コードの面倒を見てくれる機能は持ち合わせていないのです。
issuetracker.google.com
なんとかするとすると、入力した文字列から改行をとるという感じになるのでしょうか。
例えば素朴にこんな感じですかね...
var value by remember { mutableStateOf("") } TextField( value = value, onValueChange = { newValue -> value = newValue.filter { it != '\n' } }, singleLine = true )
一応これで改行は入り込まないですね。
見た目以外の問題として、物理キーボードで Enter が押されたら次の入力欄に移動したい、という要件もありそうです。
var id by remember { mutableStateOf("") } var pass by remember { mutableStateOf("") } val (idInputFocus, passInputFocus) = remember { FocusRequester.createRefs() } Column { TextField( value = id, onValueChange = { newValue -> id = newValue.filter { it != '\n' } }, modifier = Modifier .onKeyEvent { if (it.nativeKeyEvent.keyCode == KEYCODE_ENTER) { passInputFocus.requestFocus() } true } .focusRequester(idInputFocus) .focusProperties { next = passInputFocus }, ) TextField( value = pass,
これでよいのでしょうか?これではダメで、日本語入力中な場合は Enter で変換を確定するとonKeyEvent
に拾われてしまいます。なので TextField
の value には TextFieldValue を渡すことにして、composition の有無で IME が入力中としている文字列がない場合だけ Enter で次の TextField に進めるにようにしてみました。
var id by remember { mutableStateOf(TextFieldValue(text = "")) } val (idInputFocus, passInputFocus) = remember { FocusRequester.createRefs() } Column { TextField( value = id, onValueChange = { newValue -> id = newValue.copy(text = newValue.text.filter { it != '\n' } ) }, modifier = Modifier .onKeyEvent { if (it.nativeKeyEvent.keyCode == KEYCODE_ENTER && id.composition == null) { // 入力中ではない passInputFocus.requestFocus() } true } .focusRequester(idInputFocus) .focusProperties { next = passInputFocus }, ) TextField( ...
面倒ですが、現時点ではこんな感じでしょうか...