Jetpack Compose 在 TextField 末尾设置光标
Jetpack Compose setting cursor on end of TextField
想为 phone 个号码创建 TextField。
需要帮助将光标设置在字段中总是在字符串的末尾
我想做什么:
当在字段中获得新数字时,我得到所有已经输入的数字,而不是附加下划线(_)至少有 11 个字符串长度,而不是 return 带有数字的字符串或子字符串的“_”:
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, 4)}) ${template.substring(4,7)} ${template.substring(7,9)} ${template.substring(9, 11)}"
} else {
"+7(___) ___ __ __"
}
}
感谢您的帮助
它有些不同,但您可以尝试使用 visualTransformation
属性.
而不是使用 onValueChange
类似于:
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)
}
想为 phone 个号码创建 TextField。 需要帮助将光标设置在字段中总是在字符串的末尾
我想做什么: 当在字段中获得新数字时,我得到所有已经输入的数字,而不是附加下划线(_)至少有 11 个字符串长度,而不是 return 带有数字的字符串或子字符串的“_”:
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, 4)}) ${template.substring(4,7)} ${template.substring(7,9)} ${template.substring(9, 11)}"
} else {
"+7(___) ___ __ __"
}
}
感谢您的帮助
它有些不同,但您可以尝试使用 visualTransformation
属性.
而不是使用 onValueChange
类似于:
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)
}