Jetpack Compose 在 TextField 末尾设置光标

问题描述

想为电话号码创建 TextField。 需要帮助在字段中设置光标总是在字符串的末尾

我想做什么: 当在字段中得到新数字时,我得到所有已经输入的数字,然后附加下划线(_)以获得至少 11 个字符串长度,然后返回带有数字或“_”的字符串:

return "+7(${template.substring(1,4)}) ${template.substring(4,7)} ${template.substring(7,9)} ${template.substring(9,11)}" 如果光标总是在最后它可以工作,但如果不是,则数字顺序被破坏

完整代码

@Composeble

@Composable
fun PhoneNumberEditText(
    phoneNumState: MutableState<String>,modifier: Modifier = Modifier,imeAction: ImeAction = ImeAction.Done,onImeAction: () -> Unit = {}
) {
    TextField(
        shape = RoundedCornerShape(16.dp),value = phoneNumState.value,onValueChange = { value ->
            phoneNumState.value = value
            val digits = phoneNumState.value.tochararray().filter { it.isDigit() }
            phoneNumState.value = phoneNumTemplate(digits)
        },modifier = modifier
            .clip(RoundedCornerShape(16.dp))
            .size(343.dp,54.dp),singleLine = true,placeholder = {
            Text(
                "+7(___)_______",style = passwordTextStyle,)
        },colors = TextFieldDefaults.textFieldColors(
            backgroundColor = whiteBackground,focusedindicatorColor = Color.Transparent,unfocusedindicatorColor = Color.Transparent,cursorColor = greyColor,textColor = greyColor
        ),leadingIcon = {
            Image(
                painterResource(id = R.drawable.ic_phone),stringResource(id = R.string.nomad_contentDescription_icon_phone)
            )
        },keyboardOptions = KeyboardOptions(
            imeAction = imeAction,keyboardType = KeyboardType.Phone
        ),)

}
 

字符串转换器:

fun phoneNumTemplate(chars: List<Char>): String {
    return if (chars.isNotEmpty()) {
        val digits = mutablelistof<Int>()
        chars.forEach {
            digits.add(it.toString().toInt())
        }
        val template = StringBuilder()
        digits.forEach { template.append(it) }
        for (i in 0..11) {
            template.append("_")
        }
        "+7(${template.substring(1,11)}"
    } else {
        "+7(___) ___ __ __"
    }
}

感谢您的帮助

解决方法

它有些不同,但您可以尝试使用 onValueChange 属性代替 visualTransformation
类似的东西:

TextField(
    //your code...,visualTransformation = PhoneNumberTransformation()

)

与:

class PhoneNumberTransformation() : VisualTransformation {
    override fun filter(text: AnnotatedString): TransformedText {
        return phoneNumFilter(text)
    }
}

fun phoneNumFilter(text: AnnotatedString): TransformedText {

    // +X(XXX)_XXX_XX_XX
    val trimmed = if (text.text.length >= 11) text.text.substring(0..10) else text.text
    var out = ""
    for (i in trimmed.indices) {
        if (i==0) out += "+"
        if (i==1) out += "("
        out += trimmed[i]
        if (i==3) out +=") "
        if (i==6 || i==8 ) out += " "
       
    }
    
    val phoneNumberOffsetTranslator = object : OffsetMapping {
        override fun originalToTransformed(offset: Int): Int {
            if (offset <= 0) return offset
            if (offset <= 1) return offset +1
            if (offset <= 3) return offset +2
            if (offset <= 7) return offset +4
            if (offset <= 9) return offset +5
            if (offset <= 11) return offset +6
            return 17
            
        }

        override fun transformedToOriginal(offset: Int): Int {
            if (offset <=0) return offset
            if (offset <=2) return offset -1
            if (offset <=7) return offset -2
            if (offset <=12) return offset -4
            if (offset <=15) return offset -5
            if (offset <=18) return offset -6
            return 11
        }
    }

    return TransformedText(AnnotatedString(out),phoneNumberOffsetTranslator)
}

enter image description here