使用 Jetpack Compose,如何格式化 TextField 值以遵循“dd/mm/yyyy”格式?
问问题
788 次
1 回答
4
更新的答案
接受 Jetpack Compose TextField 的任何类型掩码的 VisualTranformation 的实现:
class MaskVisualTransformation(private val mask: String) : VisualTransformation {
private val specialSymbolsIndices = mask.indices.filter { mask[it] != '#' }
override fun filter(text: AnnotatedString): TransformedText {
var out = ""
var maskIndex = 0
text.forEach { char ->
while (specialSymbolsIndices.contains(maskIndex)) {
out += mask[maskIndex]
maskIndex++
}
out += char
maskIndex++
}
return TransformedText(AnnotatedString(out), offsetTranslator())
}
private fun offsetTranslator() = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
val offsetValue = offset.absoluteValue
if (offsetValue == 0) return 0
var numberOfHashtags = 0
val masked = mask.takeWhile {
if (it == '#') numberOfHashtags++
numberOfHashtags < offsetValue
}
return masked.length + 1
}
override fun transformedToOriginal(offset: Int): Int {
return mask.take(offset.absoluteValue).count { it == '#' }
}
}
}
如何使用它:
@Composable
fun DateTextField() {
var date by remember { mutableStateOf("") }
TextField(
value = date,
onValueChange = {
if (it.length <= DATE_LENGTH) {
date = it
}
},
visualTransformation = MaskVisualTransformation(DATE_MASK)
)
}
object DateDefaults {
const val DATE_MASK = "##/##/####"
const val DATE_LENGTH = 8 // Equals to "##/##/####".count { it == '#' }
}
旧答案
正如 Jetpack Compose 提供密码的可视化转换一样,我们也可以进行自己的可视化转换。
class DateTransformation : VisualTransformation {
// XX/XX/XXXX format
override fun filter(text: AnnotatedString): TransformedText {
var out = ""
text.text.forEachIndexed { index, char ->
when (index) {
2 -> out += "/$char"
4 -> out += "/$char"
else -> out += char
}
}
val numberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
if (offset <= 2) return offset
if (offset <= 4) return offset + 1
return offset + 2
}
override fun transformedToOriginal(offset: Int): Int {
if (offset <= 2) return offset
if (offset <= 5) return offset - 1
return offset - 2
}
}
return TransformedText(AnnotatedString(out), numberOffsetTranslator)
}
}
我们返回一个应用了过滤器的 TransformedText 和一个在原始文本和转换后的文本之间转换的 OffsetMapping。
现在,我们可以在任何 TextField 中使用我们的 Visual Transformation 类。
var text by remember { mutableStateOf("") }
TextField(
value = text,
visualTransformation = DateTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
onValueChange = {
if (it.length < 9) text = it
}
)
于 2021-09-24T05:09:56.050 回答