Android/Jetpack Compose
Jetpack Compose TextField 날짜, 시간 마스킹 처리
loppav6
2022. 11. 2. 15:54
TextField에 날짜나 시간 입력 시 마스킹 처리를 하고 싶을 때가 있다.
TextField의 VisualTransformation Interface를 활용해 아래와 같이 처리해보자.
ex1) 13:25
ex2) 2022-12-12
소스는 Jetpack Compose 키보드 내리기 소스를 참조하자.
https://loppav6.tistory.com/21
1. 시간 마스킹 VisualTransformation
private class TimeTransFormation() : VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
return timeFilter(text)
}
private fun timeFilter(text: AnnotatedString): TransformedText {
val trimmed = if (text.text.length >= 4) text.text.substring(0..3) else text.text
var out = ""
for (i in trimmed.indices) {
out += trimmed[i]
if (i % 2 == 1 && i < 3) out += ":"
}
val numberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
if (offset <= 1) return offset
if (offset <= 3) return offset + 1
return 5
}
override fun transformedToOriginal(offset: Int): Int {
if (offset <= 2) return offset
if (offset <= 5) return offset - 1
return 4
}
}
return TransformedText(AnnotatedString(out), numberOffsetTranslator)
}
}
2. 날짜 마스킹 VisualTransformation
fun dateFilter(text: AnnotatedString): TransformedText {
val trimmed = if (text.text.length >= 8) text.text.substring(0..7) else text.text
var out = ""
for (i in trimmed.indices) {
out += trimmed[i]
if (i == 3 || i == 5) out += "-"
}
val numberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
if (offset <= 4) return offset
if (offset <= 5) return offset + 1
if (offset <= 8) return offset + 2
return 10
}
override fun transformedToOriginal(offset: Int): Int {
if (offset <= 2) return offset
if (offset <= 5) return offset - 1
if (offset <= 10) return offset - 2
return 8
}
}
return TransformedText(AnnotatedString(out), numberOffsetTranslator)
}
3. UI
@Composable
fun MainView() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
val textFieldTime = remember { mutableStateOf("") }
val textFieldDate = remember { mutableStateOf("") }
val focusManager = LocalFocusManager.current
TextField(
value = textFieldTime.value,
onValueChange = { if (it.length <= 4) textFieldTime.value = it },
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done, keyboardType = KeyboardType.Number),
visualTransformation = TimeTransFormation(),
placeholder = { Text(text = "13:50") },
)
TextField(
value = textFieldDate.value,
onValueChange = { if (it.length <= 8) textFieldDate.value = it },
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done, keyboardType = KeyboardType.Number),
visualTransformation = DateTransformation(),
placeholder = { Text(text = "2022-11-02") },
)
Button(onClick = { focusManager.clearFocus() }, modifier = Modifier.fillMaxWidth()) {
Text(text = "닫기")
}
}
}