앱을 사용하는 도중 금액을 입력받는 상황은 자주 발생한다.
토스로 친구에게 송금을 한다던지 등등
그런 상황에서 inputType이 number 일때 어떻게 1,000,000 과 같은 쉼표를,
커서 맨 뒤에 '원' 이라는 글자를 붙힐 수 있는지 알아보자
P.S 쉼표를 찍는 법은 구글링을 통해 쉽게 검색이 되는데, 뒤에 '원'이라는 글자를 붙히는 방법은
잘 나오지 않아 누군가가 이 글을 보고 도움을 받지 않을까 해서 작성한다.
우선 쉼표를 붙혀주는 방법은 구글링을 통해 쉽게 검색을 할 수 있다.
(블로그 주인님 감사합니다. 덕분에 편하게 구현하였습니다)
https://kiwinam.com/posts/17/android-edittext-comma/
자바로 되어있는 코드이지만, 코틀린으로 쉽게 변환할 수 있기 때문에 변환해서 사용하면 된다.
문제는 원이다.
처음으로 시도했던 방법은 위에 코드에서
TextWatcher watcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if(!TextUtils.isEmpty(charSequence.toString()) && !charSequence.toString().equals(result)){
result = decimalFormat.format(Double.parseDouble(charSequence.toString().replaceAll(",","")));
wonEt.setText(result);
wonEt.setSelection(result.length());
}
}
@Override
public void afterTextChanged(Editable editable) {
}
};
result라는 결과에 '원'을 맨 뒤에 붙혀 edittext의 text 로 붙히고 다시 텍스트를 입력하려할때 droplast(1) 과 같은 확장함수를 이용해서 뺐다 붙혔다 하는 방법이었는데 원하는 결과를 얻지 못하였다. (가능은 할 것 같은데 outofindex 에러와 type casting 에러 발생위험이 클 것 같아서 방법을 우회하였다.
내가 해결한 방법은 edittext 위에 textview를 겹치게 위치해둔 다음 (INVISIBLE상태로) TextWatcher를 이용해서 edittext에 값이 변화하면(빈값 -> 입력값) textview의 text를 edittext의 text값(금액) + '원'으로 넣어주고 VISIBLE 상태로 변경해주는 방법이다.
text 값이 없다면(썼다가 다 지우면) textview에 해당 작업을 해주지 않고 다시 보이지 않도록 INVISIBLE 처리를 해주면 된다.
xml
<EditText
android:id="@+id/et_register_lesson_price"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_register_rounded_edit_text_gray"
android:hint="@string/enter_lesson_price"
android:inputType="number"
android:maxLength="9"
android:paddingHorizontal="18dp"
android:visibility="visible"
android:textSize="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_register_lesson_price" />
<TextView
android:id="@+id/tv_register_lesson_price_Info"
android:textColor="@color/black"
android:visibility="invisible"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_register_rounded_edit_text_gray"
android:gravity="center_vertical"
android:paddingHorizontal="18dp"
android:textSize="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_register_lesson_price" />
code
private fun validateInputForm(editText: EditText, button: AppCompatButton) = with(binding) {
var result = ""
val decimalFormat = DecimalFormat("#,###")
editText.addTextChangedListener(object : TextWatcher {
@RequiresApi(Build.VERSION_CODES.M)
override fun beforeTextChanged(charSequence: CharSequence?, i1: Int, i2: Int, i3: Int) {
}
override fun onTextChanged(charSequence: CharSequence?, i1: Int, i2: Int, i3: Int) {
if (!TextUtils.isEmpty(charSequence!!.toString()) && charSequence.toString() != result) {
lessonPrice = charSequence.toString().replace(",", "").toInt()
result =
decimalFormat.format(charSequence.toString().replace(",", "").toDouble())
editText.setText(result)
tvRegisterLessonPriceInfo.apply {
text = getString(R.string.input_lesson_price, result)
visibility = View.VISIBLE
}
editText.setSelection(result.length)
}
if (TextUtils.isEmpty(charSequence.toString()) && charSequence.toString() != result) {
result = ""
editText.setText(result)
tvRegisterLessonPriceInfo.apply {
text = result
visibility = View.INVISIBLE
}
}
}
// 이 밑으론 해당 글과는 딱히 관련 없는 코드로 무시해도 된다.
@RequiresApi(Build.VERSION_CODES.M)
override fun afterTextChanged(editable: Editable?) {
if (editable.isNullOrEmpty()) {
(activity as RegisterLessonActivity).lockButton(button)
} else {
(activity as RegisterLessonActivity).unlockButton(button)
}
}
})
editText.setOnFocusChangeListener { _, gainFocus ->
if (gainFocus) {
editText.setBackgroundResource(R.drawable.bg_register_rounded_edit_text_sloth)
} else {
editText.setBackgroundResource(R.drawable.bg_register_rounded_edit_text_gray)
}
}
}
strings.xml
<string name="input_lesson_price">%1$s원</string>
edittext와 textview에서 숫자+, 는 중복으로 쓰여지고
textview에만 맨 뒤에 '원'을 붙히며
edittext의 커서를 맨뒤로 보내 항상 '원'이라는 글자 바로 앞으로 나오도록 구현하였다.
(두 view에 중복적으로 글자가 작성되는게 약간 꺼려져 textview에만 글자가 쓰이도록 해보려했는데
그러면 커서의 위치가 '원'바로 앞으로 오지 않았다. 더 나은 방법이 있으면 알려주시면 감사)
실행 화면