Jetpack Compose限制TextField仅输入数字时点击小数点崩溃
问题:Jetpack Compose TextField限制数字输入时点击小数点崩溃
我想在Jetpack Compose的TextField中仅允许输入数字,参考相关逻辑限制字母和特殊字符后,点击键盘上的小数点时应用直接崩溃。
错误日志
2022-08-18 09:47:13.966 8050-8050/com.abc.app.dev E/AndroidRuntime: FATAL EXCEPTION: main Process: com.abc.app.dev, PID: 8050 java.lang.NumberFormatException: For input string: "." at java.lang.Integer.parseInt(Integer.java:733) at java.lang.Integer.parseInt(Integer.java:865) at com.abc.app.yo.composable.InputKt$InputWithUnitContainer$1$1$1$1.invoke(Input.kt:187) at com.abc.app.yo.composable.InputKt$InputWithUnitContainer$1$1$1$1.invoke(Input.kt:186) at androidx.compose.foundation.text.BasicTextFieldKt$BasicTextField$7$1.invoke(BasicTextField.kt:266) at androidx.compose.foundation.text.BasicTextFieldKt$BasicTextField$7$1.invoke(BasicTextField.kt:264) at androidx.compose.foundation.text.CoreTextFieldKt$CoreTextField$onValueChangeWrapper$1.invoke(CoreTextField.kt:241) at androidx.compose.foundation.text.CoreTextFieldKt$CoreTextField$onValueChangeWrapper$1.invoke(CoreTextField.kt:236) at androidx.compose.foundation.text.TextFieldDelegate$Companion.onEditCommand(TextFieldDelegate.kt:198) at androidx.compose.foundation.text.TextFieldDelegate$Companion.access$onEditCommand(TextFieldDelegate.kt:90) at androidx.compose.foundation.text.TextFieldDelegate$Companion$restartInput$1.invoke(TextFieldDelegate.kt:246) at androidx.compose.foundation.text.TextFieldDelegate$Companion$restartInput$1.invoke(TextFieldDelegate.kt:243) at androidx.compose.ui.text.input.TextInputServiceAndroid$createInputConnection$1.onEditCommands(TextInputServiceAndroid.android.kt:111) at androidx.compose.ui.text.input.RecordingInputConnection.endBatchEditInternal(RecordingInputConnection.android.kt:162) at androidx.compose.ui.text.input.RecordingInputConnection.addEditCommandWithBatch(RecordingInputConnection.android.kt:136) at androidx.compose.ui.text.input.RecordingInputConnection.commitText(RecordingInputConnection.android.kt:181) at com.android.internal.inputmethod.RemoteInputConnectionImpl.lambda$commitText$16$com-android-internal-inputmethod-RemoteInputConnectionImpl(RemoteInputConnectionImpl.java:569) at com.android.internal.inputmethod.RemoteInputConnectionImpl$$ExternalSyntheticLambda34.run(Unknown Source:8) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7898) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
相关代码
传递的参数:
appendTextFieldValue: (TextFieldValue) -> Unit,
TextField实现:
TextField( value = textFieldValue, singleLine = true, onValueChange = { if (it.text.length <= maxLength && it.text.toInt() <= maxLength) { appendTextFieldValue(it) } onIsErrorChange(false) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), isError = isError, )
解决方案
崩溃原因:点击小数点后输入框内容变为.,此时调用it.text.toInt()会抛出NumberFormatException,因为.无法转换为整数。
修复方案如下:
方案1:严格过滤非数字字符
直接过滤输入中的非数字内容,从根源避免无效输入:
onValueChange = { newVal -> val filteredText = newVal.text.filter { it.isDigit() } if (filteredText.length <= maxLength) { val numericValue = if (filteredText.isEmpty()) 0 else filteredText.toInt() if (numericValue <= maxLength) { appendTextFieldValue(newVal.copy(text = filteredText)) } } onIsErrorChange(false) }
方案2:安全转换整数
通过runCatching捕获转换异常,仅在转换成功时更新输入框:
onValueChange = { newVal -> val inputText = newVal.text if (inputText.length <= maxLength) { runCatching { inputText.toInt() } .onSuccess { num -> if (num <= maxLength) { appendTextFieldValue(newVal) } } } onIsErrorChange(false) }
如果需要支持小数输入,需将toInt()改为toDouble(),同时把keyboardType改为KeyboardType.Decimal;若仅需整数输入,优先选择方案1,体验更流畅。
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

