NumberPickerでの値の選択ではスワイプによる選択とテキスト入力による選択があります。
スワイプの場合は問題ないのですが、テキスト入力の場合は確定しないといけません。「テキスト入力したが確定していない」という状態では変更前の値になっています。
入力したら即時反映してくれるように動作を変えたいと思います。
NumberPicker内のEditTextのイベントリスナーで処理
EditTextの取得
NumberPickerはLinearLayoutの子クラスなので、子要素を取得できます。
val picker = view.findViewById(R.id.number_picker)
val editText = picker.children.filterIsInstance<EditText>().first()
のようにしてEditTextを取得できます。
イベントリスナーの設定
取得したEditTextに入力された時点で値を反映するイベントリスナーを設定します。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
view.main_number_picker.also {
it.minValue = 0
it.maxValue = 99
it.findInput().addTextChangedListener(
afterTextChanged = { s ->
s.toString().toIntOrNull()?.let { inputNum ->
it.value = inputNum
}
}
)
it.value = viewModel.num
it.setOnValueChangedListener { _, _, newVal ->
viewModel.num = newVal
}
}
}
復元時の挙動
NumberPickerが一つだけならここまでで良いのですが複数存在している場合はもうひと工夫必要です。
画面回転などで再描画されるとSavedInstanceStateからEditTextの値を復元する過程で正しくない値が入力されてしまいます。
onViewStateRestoredのタイミングで改めて復元する処理を追加しておくのがベターでしょう。
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
val view = requireView()
view.main_number_picker.value = viewModel.num
view.main_number_picker2.value = viewModel.num2
}