Skip to content

Instantly share code, notes, and snippets.

@Bloody-Badboy
Created December 10, 2020 08:32
Show Gist options
  • Save Bloody-Badboy/6e866bfc8a99f799e1924a87169adb11 to your computer and use it in GitHub Desktop.
Save Bloody-Badboy/6e866bfc8a99f799e1924a87169adb11 to your computer and use it in GitHub Desktop.
import android.content.Context
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.TextWatcher
import android.util.AttributeSet
import android.widget.EditText
import androidx.appcompat.widget.AppCompatEditText
import java.text.SimpleDateFormat
import java.util.*
class MMDDYYYYEditText @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = androidx.appcompat.R.attr.editTextStyle
) : AppCompatEditText(context, attrs, defStyleAttr) {
var onDateFilled: ((Date) -> Unit)? = null
init {
MMDDYYYYInputHelper(this) {
onDateFilled?.invoke(it)
}
}
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
val len = text?.length ?: 0
setSelection(len)
super.onSelectionChanged(len, len)
}
internal class MMDDYYYYInputHelper(
private val editText: EditText,
private val onDateFilled: (Date) -> Unit
) :
TextWatcher {
companion object {
private const val HINT = "MM/DD/YYYY"
private val dateFormat = SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH)
}
private var changeHandled = false
init {
editText.hint = HINT
editText.inputType = InputType.TYPE_CLASS_NUMBER
editText.addTextChangedListener(this)
editText.filters = arrayOf(InputFilter.LengthFilter(HINT.length))
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
var value = s.toString()
if (changeHandled) {
changeHandled = false
return
}
changeHandled = true
if (value.length >= 2) {
val month = value.substring(0, 2).toInt()
if (month > 12 || month == 0) {
value = "12"
}
}
value = addDivider(value, 2, start, before)
if (value.length >= 5) {
var day = value.substring(3, 5).toInt()
if (day > 31 || day == 0) {
value = value.replace(day.toString(), "31")
day = 31
}
val month = value.substring(0, 2).toInt()
if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) {
value = value.replace(day.toString(), "30")
} else if (month == 2 && day == 31) {
value = value.replace(day.toString(), "29")
}
}
value = addDivider(value, 5, start, before)
editText.setText(value)
editText.setSelection(editText.text?.length ?: 0)
}
override fun afterTextChanged(s: Editable) {
if (s.length == HINT.length) {
try {
dateFormat.parse(s.toString())?.let { onDateFilled.invoke(it) }
} catch (t: Throwable) {
}
}
}
private fun addDivider(working: String, position: Int, start: Int, before: Int): String {
if (working.length == position) {
return if (before <= position && start < position)
"$working/"
else
working.dropLast(1)
}
return working
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment