How can I format an EditText
to follow the \"dd/mm/yyyy
\" format the same way that we can format using a TextWatcher
to mask
Juan Cortés' wiki works like a charm https://stackoverflow.com/a/16889503/3480740
Here my Kotlin version
fun setBirthdayEditText() {
birthdayEditText.addTextChangedListener(object : TextWatcher {
private var current = ""
private val ddmmyyyy = "DDMMYYYY"
private val cal = Calendar.getInstance()
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
if (p0.toString() != current) {
var clean = p0.toString().replace("[^\\d.]|\\.".toRegex(), "")
val cleanC = current.replace("[^\\d.]|\\.", "")
val cl = clean.length
var sel = cl
var i = 2
while (i <= cl && i < 6) {
sel++
i += 2
}
//Fix for pressing delete next to a forward slash
if (clean == cleanC) sel--
if (clean.length < 8) {
clean = clean + ddmmyyyy.substring(clean.length)
} else {
//This part makes sure that when we finish entering numbers
//the date is correct, fixing it otherwise
var day = Integer.parseInt(clean.substring(0, 2))
var mon = Integer.parseInt(clean.substring(2, 4))
var year = Integer.parseInt(clean.substring(4, 8))
mon = if (mon < 1) 1 else if (mon > 12) 12 else mon
cal.set(Calendar.MONTH, mon - 1)
year = if (year < 1900) 1900 else if (year > 2100) 2100 else year
cal.set(Calendar.YEAR, year)
// ^ first set year for the line below to work correctly
//with leap years - otherwise, date e.g. 29/02/2012
//would be automatically corrected to 28/02/2012
day = if (day > cal.getActualMaximum(Calendar.DATE)) cal.getActualMaximum(Calendar.DATE) else day
clean = String.format("%02d%02d%02d", day, mon, year)
}
clean = String.format("%s/%s/%s", clean.substring(0, 2),
clean.substring(2, 4),
clean.substring(4, 8))
sel = if (sel < 0) 0 else sel
current = clean
birthdayEditText.setText(current)
birthdayEditText.setSelection(if (sel < current.count()) sel else current.count())
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(p0: Editable) {
}
})
}
Kotlin version without validation
editText.addTextChangedListener(object : TextWatcher{
var sb : StringBuilder = StringBuilder("")
var _ignore = false
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if(_ignore){
_ignore = false
return
}
sb.clear()
sb.append(if(s!!.length > 10){ s.subSequence(0,10) }else{ s })
if(sb.lastIndex == 2){
if(sb[2] != '/'){
sb.insert(2,"/")
}
} else if(sb.lastIndex == 5){
if(sb[5] != '/'){
sb.insert(5,"/")
}
}
_ignore = true
editText.setText(sb.toString())
editText.setSelection(sb.length)
}
})
add android:inputType="date"
to your EditText