Last active
March 19, 2024 23:19
-
-
Save behdad222/60b4f99ceff14167b1299cb387ef4b20 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PriceTextInputLayout @JvmOverloads constructor( | |
context: Context, | |
attrs: AttributeSet? = null, | |
defStyleAttr: Int = R.attr.textInputStyle | |
) : TextInputLayout(context, attrs, defStyleAttr) { | |
val locale = Locale(LOCALE_LANGUAGE_FA) | |
override fun onAttachedToWindow() { | |
super.onAttachedToWindow() | |
editText?.apply { | |
doAfterTextChanged { editable -> | |
if (editable == null) { | |
return@doAfterTextChanged | |
} | |
val content = editable.toString().getNumber() | |
val formattedPersian = String.format(locale, "%d", content) | |
if (formattedPersian != editable.toString()) { | |
var selectionPosition = selectionStart.orZero() | |
setText(formattedPersian) | |
if (selectionPosition == 0 || selectionPosition > text.length) { | |
selectionPosition = text.length.orZero() | |
} | |
setSelection(selectionPosition) | |
return@doAfterTextChanged | |
} | |
val separatorWidth = paint.measureText(SEPARATED_CHAR.toString()).toInt().orZero() | |
formatThousandsSeparator(editable, separatorWidth) | |
} | |
} | |
} | |
private fun formatThousandsSeparator(editable: Editable, separatorWidth: Int) { | |
val textLength = editable.length | |
// first remove any previous span | |
val spans = editable.getSpans( | |
0, editable.length, | |
SeparatorSpan::class.java | |
) | |
for (i in spans.indices) { | |
editable.removeSpan(spans[i]) | |
} | |
for (i in textLength - 1 downTo 0) { | |
val marginSPan = SeparatorSpan(separatorWidth) | |
editable.setSpan(marginSPan, i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) | |
} | |
} | |
class SeparatorSpan(private val separatorWidth: Int) : ReplacementSpan() { | |
override fun getSize( | |
paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt? | |
): Int { | |
val widths = FloatArray(end - start) | |
paint.getTextWidths(text, start, end, widths) | |
var sum = 0 | |
for (i in widths.indices) { | |
sum += widths[i].toInt() | |
} | |
val formattedText = makeFormattedText(text) | |
val newStart = getNewStart(start, formattedText) | |
if (formattedText[newStart] == SEPARATED_CHAR) { | |
sum += separatorWidth | |
} | |
return sum | |
} | |
override fun draw( | |
canvas: Canvas, | |
text: CharSequence, | |
start: Int, | |
end: Int, | |
x: Float, | |
top: Int, | |
y: Int, | |
bottom: Int, | |
paint: Paint | |
) { | |
val formattedText = makeFormattedText(text) | |
val newStart = getNewStart(start, formattedText) | |
var numberChar = 1 | |
if (formattedText[newStart] == SEPARATED_CHAR) { | |
numberChar++ | |
} | |
canvas.drawText( | |
formattedText, | |
newStart, newStart + numberChar, | |
x, y.toFloat(), | |
paint | |
) | |
} | |
private fun makeFormattedText(text: CharSequence): String { | |
val formattedText = StringBuilder(text) | |
var thoseGroupIndex = 0 | |
for (i in text.length - 1 downTo 0) { | |
thoseGroupIndex++ | |
if (thoseGroupIndex % 3 == 0 && i != 0) { | |
formattedText.insert(i, SEPARATED_CHAR) | |
} | |
} | |
return formattedText.toString() | |
} | |
private fun getNewStart(start: Int, text: String): Int { | |
var i = 0 | |
var newStart = start | |
while (i < newStart) { | |
if (text[i] == SEPARATED_CHAR) { | |
newStart++ | |
} | |
i++ | |
} | |
return newStart | |
} | |
} | |
companion object { | |
const val LOCALE_LANGUAGE_FA = "fa" | |
const val SEPARATED_CHAR = '٬' | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
input.mp4