{
金額などの数値を入力してもらう際に、値を変更する度にカンマ区切りに自動整形するEditTextを実装してみました。EditTextを継承して作ってます。
CurrencyEditText.kt
class CurrencyEditText : android.support.v7.widget.AppCompatEditText {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
private var prevText = text.toString()
private val watcher:TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
prevText = s.toString()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val text = s?.toString() ?: return
if (prevText == text) return
val number = text.replace(",", "").toLongOrNull() ?: return
val textWithComma = number.toStringWithSeparator()
if (textWithComma == text) return
val countRightFromCursor = text.length - selectionEnd
setTextKeepState(textWithComma)
setSelection((textWithComma.length - countRightFromCursor).coerceAtLeast(0))
}
}
init {
addTextChangedListener(watcher)
}
}
fun Number.toStringWithSeparator() = "%,d".format(this)
あとは普通にレイアウトxmlで使うだけ。
<itmammoth.hoge.CurrencyEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
/>
苦労した点
カンマ区切りに整形した文字列をsetTextすることで、直前のカーソル位置からずれてしまうということが起こりました。気持ち悪いので、setSelection
でカーソル位置を戻してます。
あと、値に変更がない場合はonTextChanged内でスルッとreturnしてます。これがないと無限ループに陥ります。
改善したい点
スタイルが素の状態(?)になってしまい、AppThemeのEditTextのスタイルが適用されません。レイアウトxmlstyle
を指定しないと浮いた感じになってしまうと思います。CurrencyEditText
の中で、コードでデフォルトスタイルを適用するとかしないといけないのかなあ・・・?
追記) EditText
ではなくandroid.support.v7.widget.AppCompatEditText
を継承すべきでしたね・・・。これで解決です。修正しました。
}
簡易実装なのでテスト充分とはいえないのですが、今の所まともに動いてるようです。なんかあったらコメントください。