728x90
Android Compose의 숫자를 포맷팅하여 아래와 같은 결과를 만드려고한다 !
내가 구현하고 싶은 목표
1. 가장 앞에 원달러 문자가 붙어있어야한다.
2. 숫자를 입력할수록 단위별로 , 문자가 붙는다.
3. 값이 없을경우 항상 0 이 기본값으로 지정된다.
위와 같이 만들기 위해서는 TextField의 visualTransformation 값을 지정해야하는데
내가 원하는 기본 제공값은 없어서 VisualTransformation을 구현하기로 하였다.
class DecimalMarkedNumberVisualTransformation(
val prefix: String
) : VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
val defaultValue = "0"
val formattedText =
NumberUtil.convertNumberToDecimalMarkedString(
text.text
.filter { "^[0-9]".toRegex().matches(it.toString()) }
.ifEmpty { defaultValue }
.toLong()
)
val offsetMapping = object : OffsetMapping {
val initSize = prefix.length + defaultValue.length
override fun originalToTransformed(offset: Int): Int {
val commas = formattedText.count { it == ',' }
return if (offset == 0) initSize else offset + commas + prefix.length
}
override fun transformedToOriginal(offset: Int): Int {
val commas = formattedText.count { it == ',' }
return offset + commas + prefix.length
}
}
return TransformedText(
text = AnnotatedString("$prefix$formattedText"),
offsetMapping = offsetMapping
)
}
}
object NumberUtil {
fun convertNumberToDecimalMarkedString(number: Long): String {
return NumberFormat.getNumberInstance(Locale.getDefault()).format(number)
}
}
설명
- 생성자에 prefix를 넣음으로써 원달러가 아닌 다른 기호도 허용하도록 구현하였다.
(prefix 뿐 아니라 postfix 등 다양하게 구현이 가능할 것 같다) - 기본값을 0으로 지정하여 입력되는 값이 없을 경우에 지정해준다.
- 입력값을 항상 숫자로 필터링한다.
(해당 VisualTransformation을 정확한 동작으로 사용하기 위해서 숫자외 다른 문자가 입력되는 것을 막는 방어코드가 필요할 것 같다) - 아무것도 입력되지 않았을때 기본 커서의 위치를 잡아주기 위해 initSize 를 지정해준다.
위의 VisualTransformation을 TextField에 파라미터로 넣어주면 위와 같이 동작한다 !
@Composable
fun NumberTextField(
...
) {
TextField(
...
visualTransformation = DecimalMarkedNumberVisualTransformation("Some Prefix"),
...
)
}
728x90
댓글