Created
December 10, 2020 08:32
-
-
Save Bloody-Badboy/6e866bfc8a99f799e1924a87169adb11 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
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