Как замаскировать EditText, чтобы показать формат даты dd / mm / yyyy

Как я могу форматировать EditText чтобы следовать формату « dd/mm/yyyy » так же, как мы можем форматировать, используя TextWatcher чтобы замаскировать пользовательский ввод, чтобы он выглядел как «0,05 €». Я не говорю об ограничении символов или подтверждении даты, просто маскируя предыдущий формат.

Solutions Collecting From Web of "Как замаскировать EditText, чтобы показать формат даты dd / mm / yyyy"

Я написал этот TextWatcher для проекта, надеюсь, это будет полезно кому-то. Обратите внимание, что он не подтверждает дату, введенную пользователем, и вы должны обращаться с этим, когда фокус изменяется, поскольку пользователь, возможно, не закончил вводить дату.

Update 25/06 Сделал это wiki, чтобы узнать, достигли ли мы лучшего финального кода.

Обновление 07/06 Я, наконец, добавил некоторую валидацию самому наблюдателю. Он будет делать следующие действия с недопустимыми датами:

  • Если месяц больше 12, это будет 12 (декабрь)
  • Если дата больше той, которая была выбрана для выбранного месяца, сделайте ее максимальной для этого месяца.
  • Если год не находится в диапазоне 1900-2100 , измените его на диапазон

Эта проверка подходит для моих потребностей, но некоторые из вас могут немного изменить ее, диапазоны легко меняются, и вы можете подключить эту проверку к сообщению Toast например, чтобы уведомить пользователя о том, что мы изменили его / ее дату, поскольку он Недействителен.

В этом коде я буду предполагать, что у нас есть ссылка на нашу EditText называемую date , к которой прикреплен этот TextWatcher , это можно сделать примерно так:

 EditText date; date = (EditText)findViewById(R.id.whichdate); date.addTextChangedListener(tw); 

 TextWatcher tw = new TextWatcher() { private String current = ""; private String ddmmyyyy = "DDMMYYYY"; private Calendar cal = Calendar.getInstance(); 

Когда пользователь меняет текст EditText

  @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (!s.toString().equals(current)) { String clean = s.toString().replaceAll("[^\\d.]", ""); String cleanC = current.replaceAll("[^\\d.]", ""); int cl = clean.length(); int sel = cl; for (int i = 2; i <= cl && i < 6; i += 2) { sel++; } //Fix for pressing delete next to a forward slash if (clean.equals(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 int day = Integer.parseInt(clean.substring(0,2)); int mon = Integer.parseInt(clean.substring(2,4)); int year = Integer.parseInt(clean.substring(4,8)); if(mon > 12) mon = 12; cal.set(Calendar.MONTH, mon-1); year = (year<1900)?1900:(year>2100)?2100:year; cal.set(Calendar.YEAR, year); // ^ first set year for the line below to work correctly //with leap years - otherwise, date eg 29/02/2012 //would be automatically corrected to 28/02/2012 day = (day > cal.getActualMaximum(Calendar.DATE))? cal.getActualMaximum(Calendar.DATE):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 = sel < 0 ? 0 : sel; current = clean; date.setText(current); date.setSelection(sel < current.length() ? sel : current.length()); } } 

Мы также реализуем две другие функции, потому что мы должны

  @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void afterTextChanged(Editable s) {} }; 

Это приводит к следующему эффекту, при котором удаление или вставка символов откроет или скроет маску dd/mm/yyyy . Его нужно легко модифицировать, чтобы соответствовать другим форматным маскам, поскольку я старался оставить код как можно более простым.

Введите описание изображения здесь