尝试在 TextField 中使用 VisualTransformation 时应用崩溃

App crashes when trying to use VisualTransformation in a TextField

提问人:Murphler 提问时间:8/29/2023 更新时间:10/11/2023 访问量:240

问:

所以我正在尝试在这个线程中实现最高答案

StackOverflow 演示

以及按照以下视频进行操作

YouTube 演示

该应用程序构建良好,但是一旦我单击 TextField 开始插入数据,应用程序就会崩溃并出现以下错误(我认为堆栈跟踪太大而无法复制)

java.lang.IllegalStateException: OffsetMapping.transformedToOriginal returned invalid mapping: 12 -> 10 is not in range of original text [0, 0]

我根本看不出问题出在哪里,因为除了对蒙版和偏移量进行小改动以适应我想要的格式外,基本上没有偏离给出的示例。但据我所知,这些应该没问题。我的代码示例如下。

    @Composable
fun DisplayPhoneNumberTextField() {

    var mobileNo by remember {
        mutableStateOf("")
    }

    OutlinedTextField(
        value = mobileNo,
        onValueChange = { mobileNo = it},
        modifier = Modifier.fillMaxWidth(),
        placeholder = {
            Text(text = "Phone Number")
        },
        singleLine = true,
        colors = TextFieldDefaults.textFieldColors(
            focusedIndicatorColor = MaterialTheme.colors.secondary
        ),
        visualTransformation = {
            phoneNumberInputFormatter(it)
        },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
    )
}


private fun phoneNumberInputFormatter(text : AnnotatedString) : TransformedText {

    val mask = "xxx-xxx-xxxx"

    val trimmed = if(text.text.length >= 10) text.text.substring(0..9) else text.text

    val annotatedString = AnnotatedString.Builder().run {
        for (i in trimmed.indices){
            append(trimmed[i])
            if (i == 2 || i == 5){
                append("-")
            }
        }
        pushStyle(SpanStyle(color = Color.LightGray))
        append(mask.takeLast(mask.length - length))
        toAnnotatedString()
    }

    val phoneNumberOffsetTranslator = object : OffsetMapping {
        override fun originalToTransformed(offset: Int): Int {
            if (offset <= 2) return offset
            if (offset <= 5) return offset + 1
            if (offset <= 9) return offset + 2
            return 12
        }

        override fun transformedToOriginal(offset: Int): Int {
            if (offset <= 2) return offset
            if (offset <= 5) return offset - 1
            if (offset <= 9) return offset - 2
            return 10
        }
    }

    return TransformedText(annotatedString, phoneNumberOffsetTranslator)

}

任何帮助将不胜感激

Kotlin Android-Studio android-jetpack-compose

评论

0赞 Redek 11/16/2023
崩溃是以下行的结果:append(mask.takeLast(mask.length - length))。我还没有调试为什么,但快速解决方法是删除正在附加的掩码
0赞 Redek 11/16/2023
您的 OffsetMapping 也可能有问题。有关详细信息 developer.android.com/reference/kotlin/androidx/compose/ui/text/ 请参阅此示例...

答:

-1赞 Megh 8/29/2023 #1

看起来像可能是重复的: 致命异常:java.lang.IllegalArgumentException offset(23) 超出范围 [0, 0] JetPack Compose OutlinedTextField 即,映射完成时输入为空

也许您可以尝试像这样返回,而不是自定义转换:TransformedText

return TransformedText(annotatedString, OffsetMapping.Identity)

或者,您可以尝试上面提供的解决方案,例如,当输入为空且有输入时返回OffsetMapping.IdentitycustomMapping

评论

0赞 starball 8/31/2023
如果你认为它是重复的,那你为什么要把它标记为一个?
0赞 Michael Alan Huff 10/11/2023 #2

@murphler,我在这里可能是错的,但我认为您的掩码变量正在添加到总长度中,这就是它抵消它崩溃的原因。尝试制作,看看是否有帮助。mask = ""