Skip to content

Instantly share code, notes, and snippets.

@am3n
Created December 4, 2019 07:45
Show Gist options
  • Save am3n/f0aff1e3c1403cece807b259a29dc73f to your computer and use it in GitHub Desktop.
Save am3n/f0aff1e3c1403cece807b259a29dc73f to your computer and use it in GitHub Desktop.
package ir.dariacard
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import androidx.annotation.NonNull
import androidx.appcompat.widget.AppCompatEditText
import java.lang.Exception
import java.text.NumberFormat
/*
how to use:
edtCard?.addTextChangedListener(SerialCardTextWatcher(edtCard))
*/
abstract class BaseTextWatcher : TextWatcher {
var beforeText: String = ""
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
beforeText = s.toString()
}
abstract fun format(@NonNull amount: String): String
protected fun removeNonNumeric(@NonNull numberString: String): String {
var numbers = ""
for (i in numberString) {
if (i.isDigit())
numbers += i
}
return numbers
}
protected fun getNewCursorPosition(digitCountToRightOfCursor: Int, numberString: String): Int {
var position = 0
var c = digitCountToRightOfCursor
for (i in numberString.reversed()) {
if (c == 0)
break
if (i.isDigit())
c--
position++
}
return numberString.length - position
}
protected fun getNumberOfDigits(@NonNull text: String): Int {
var count = 0
for (i in text)
if (i.isDigit())
count++
return count
}
}
class SerialCardTextWatcher(private val editText: AppCompatEditText) : BaseTextWatcher() {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s == null) return
// 1. get cursor position : p0 = start + before
val initialCursorPosition = start + before
//2. get digit count after cursor position : c0
val numOfDigitsToRightOfCursor = getNumberOfDigits(
beforeText.substring(initialCursorPosition, beforeText.length)
)
val newAmount = format(s.toString())
editText.removeTextChangedListener(this)
editText.setText(newAmount)
//set new cursor position
try {
editText.setSelection(getNewCursorPosition(numOfDigitsToRightOfCursor, newAmount))
} catch (e: Exception) {
e.printStackTrace()
}
editText.addTextChangedListener(this)
}
override fun format(amount: String): String {
val result = removeNonNumeric(amount)
val amt = if (!TextUtils.isEmpty(result) && TextUtils.isDigitsOnly(result)) result else ""
var res = ""
for (i in amt.indices) {
if (i != 0 && i % 4 == 0)
res += " - "
res += amt[i]
}
return res
}
}
class CostTextWatcher(private val editText: AppCompatEditText) : BaseTextWatcher() {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s == null) return
// 1. get cursor position : p0 = start + before
val initialCursorPosition = start + before
//2. get digit count after cursor position : c0
val numOfDigitsToRightOfCursor = getNumberOfDigits(
beforeText.substring(initialCursorPosition, beforeText.length)
)
val newAmount = format(s.toString())
editText.removeTextChangedListener(this)
editText.setText(newAmount)
//set new cursor position
try {
editText.setSelection(getNewCursorPosition(numOfDigitsToRightOfCursor, newAmount))
} catch (e: Exception) {
e.printStackTrace()
}
editText.addTextChangedListener(this)
}
override fun format(amount: String): String {
val result = removeNonNumeric(amount)
var amt: Long? = if (!TextUtils.isEmpty(result) && TextUtils.isDigitsOnly(result)) result.toLongOrNull() else 0
if (amt == null) {
amt = result.substring(0, 15).toLong()
}
val formatter = NumberFormat.getNumberInstance()
//return formatter.format(amt).plus(" ﷼")
//return "﷼ ".plus(formatter.format(amt))
return formatter.format(amt)
}
}
class PostalCodeTextWatcher(private val editText: AppCompatEditText) : BaseTextWatcher() {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s == null) return
// 1. get cursor position : p0 = start + before
val initialCursorPosition = start + before
//2. get digit count after cursor position : c0
val numOfDigitsToRightOfCursor = getNumberOfDigits(
beforeText.substring(initialCursorPosition, beforeText.length)
)
val newAmount = format(s.toString())
editText.removeTextChangedListener(this)
editText.setText(newAmount)
//set new cursor position
try {
editText.setSelection(getNewCursorPosition(numOfDigitsToRightOfCursor, newAmount))
} catch (e: Exception) {
e.printStackTrace()
}
editText.addTextChangedListener(this)
}
override fun format(amount: String): String {
val result = removeNonNumeric(amount)
val amt = if (!TextUtils.isEmpty(result) && TextUtils.isDigitsOnly(result)) result else ""
var res = ""
for (i in amt.indices) {
if (i != 0 && i % 5 == 0)
res += "-"
res += amt[i]
}
return res
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment