无法使用当前 SaveableStateRegistry 保存包含 TextFieldValue(text='', Selection=TextRange(0, 0), Composition=null) 的 MutableState

Spa*_*tta 13 android textfield android-jetpack-compose

我试图实现我的 TextField 只能接受 10 位数字的要求,并且我使用了“rememberSaveable”,以便当用户导航到另一个屏幕然后返回到此屏幕时,在 TextField 中输入的数字不会丢失。

我使用过 RememberSaveable,例如:

通过 RememberSaveable 进行 var 查询 { mutableStateOf(TextFieldValue("")) }

然后我在 TextField 中使用它:

            val maxChar = 10

            TextField(
                    value = query,
                    onValueChange = {
                        if (it.text.length <= maxChar) query = it
                    },
                label = {
                    Text(
                        "Name as on PAN Card",
                        color = colorResource(id = R.color.bright_green),
                        fontSize = with(LocalDensity.current) { dimensionResource(id = R.dimen._12ssp).toSp() },
                        fontFamily = FontFamily(Font(R.font.poppins_regular)),
                        textAlign = TextAlign.Left

                    )
                },
                interactionSource = interactionSource,
                keyboardOptions = KeyboardOptions(keyboardType =KeyboardType.Number),


                    textStyle = TextStyle(
                    textAlign = TextAlign.Start,
                    color = colorResource(id = R.color.bright_green),
                    fontFamily = FontFamily(Font(R.font.poppins_regular)),

                    fontSize = with(LocalDensity.current) { dimensionResource(id = R.dimen._12ssp).toSp() }
                ),
                modifier = Modifier
                        .drawBehind {
                            val strokeWidth = indicatorWidth.value * density
                            val y = size.height - strokeWidth / 2
                            drawLine(
                                    indicatorColor,
                                    Offset(TextFieldPadding.toPx(), y),
                                    Offset(size.width - TextFieldPadding.toPx(), y),
                                    strokeWidth
                            )
                        }
                        .constrainAs(name) {
                            bottom.linkTo(glNameBottom)
                            start.linkTo(glLeft)
                            end.linkTo(glRight)
                            width = Dimension.fillToConstraints
                        }
                        .height((mHeight.value / 10.5).dp),
                colors = TextFieldDefaults.textFieldColors(
                    backgroundColor = Color.Transparent,
                    cursorColor = colorResource(id = R.color.bright_green),
                    focusedIndicatorColor = Transparent,
                    unfocusedIndicatorColor = Transparent,
                    disabledIndicatorColor = Transparent
                )
            )
Run Code Online (Sandbox Code Playgroud)

但是在使用上面的代码时我得到了异常:

java.lang.IllegalArgumentException: MutableState containing TextFieldValue(text='', selection=TextRange(0, 0), composition=null) cannot be saved using the current SaveableStateRegistry. The default implementation only supports types which can be stored inside the Bundle. Please consider implementing a custom Saver for this class and pass it as a stateSaver parameter to rememberSaveable().
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

Rob*_*rdi 36

正如文档中所建议的BasicTextField,您可以简单地使用TextFieldValue.Saver

var query by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue("")) }
Run Code Online (Sandbox Code Playgroud)

  • 如果您看到“rememberSaveable()”参数全部呈红色波浪线,请确保使用“stateSaver”作为参数名称。实际上有两个 `rememberSaveable()` 函数 - 在另一个函数中,参数称为 `saver` 并且它不接受 init 块中的 `mutableStateOf()` 。 (2认同)

Ric*_*per 0

这是因为rememberSaveable不支持存储TextFieldValue。根据文档,您可以创建一个自定义保护程序对象,但更好的解决方案是将您的值简单地存储在视图模型中。这样,在整个配置更改和导航过程中都会记住它。另外,我不认为rememberSaveable在导航中提供状态保存,因此当您返回屏幕时,文本无论如何都会丢失(您可以通过将初始化更改为 来尝试var query by rememberSaveable { mutableStateOf("") }

只需创建一个视图模型

class VM: ViewModel(){
 var query by mutableStateOf(TextFieldValue(""))
 private set

 fun onQueryChange(newQuery: textFieldCount){
       if (newQuery.text.length <= maxChar) query = newQuery
 }
}
Run Code Online (Sandbox Code Playgroud)

是的,应该这样做

在你的班级里,

            val maxChar = 10

            TextField(
                    value = viewmodel.query,
                    onValueChange = viewmodel::onQueryChange,
                label = {
                    Text(
                        "Name as on PAN Card",
                        color = colorResource(id = R.color.bright_green),
                        fontSize = with(LocalDensity.current) { dimensionResource(id = R.dimen._12ssp).toSp() },
                        fontFamily = FontFamily(Font(R.font.poppins_regular)),
                        textAlign = TextAlign.Left

                    )
                },
                interactionSource = interactionSource,
                keyboardOptions = KeyboardOptions(keyboardType =KeyboardType.Number),


                    textStyle = TextStyle(
                    textAlign = TextAlign.Start,
                    color = colorResource(id = R.color.bright_green),
                    fontFamily = FontFamily(Font(R.font.poppins_regular)),

                    fontSize = with(LocalDensity.current) { dimensionResource(id = R.dimen._12ssp).toSp() }
                ),
                modifier = Modifier
                        .drawBehind {
                            val strokeWidth = indicatorWidth.value * density
                            val y = size.height - strokeWidth / 2
                            drawLine(
                                    indicatorColor,
                                    Offset(TextFieldPadding.toPx(), y),
                                    Offset(size.width - TextFieldPadding.toPx(), y),
                                    strokeWidth
                            )
                        }
                        .constrainAs(name) {
                            bottom.linkTo(glNameBottom)
                            start.linkTo(glLeft)
                            end.linkTo(glRight)
                            width = Dimension.fillToConstraints
                        }
                        .height((mHeight.value / 10.5).dp),
                colors = TextFieldDefaults.textFieldColors(
                    backgroundColor = Color.Transparent,
                    cursorColor = colorResource(id = R.color.bright_green),
                    focusedIndicatorColor = Transparent,
                    unfocusedIndicatorColor = Transparent,
                    disabledIndicatorColor = Transparent
                )
            )

Run Code Online (Sandbox Code Playgroud)