Skip to content

FormatWatcher и форматирование в EditText "на лету"

Mikhail Artemev edited this page Oct 31, 2016 · 3 revisions

В ситуациях, когда необходимо форматировать текст в TextView "на лету", например во время ввода пользователем текста в EditText, нам необходимо постоянно модифицировать текст внутри маски. Для этой цели используется абстрактный класс FormatWatcher (aka форматтер). Класс создержит внутри маску и синхронизирует содержмое TextView с ней. Он инкапсулирует создание маски и работу с ней. Создание маски не определено в базовом классе и дожно быть реализовано в наследниках. Форматтер устанавливается на TextView и отслеживает изменения текста с помощью механизма TextWatcher.

ВАЖНО: не рекомендуется ипользование форматтера вместе с другими TextWatcher'ами. Для получения оповещений об изменении текста в TextView можно использовать FormattedTextChangeListener. Он устанавливается на форматтер методом FormatWatcher#setCallback(FormattedTextChangeListener).

В Decoro предоставлены две реализации FormatWatcher: DescriptorFormatWatcher и MaskFormatWatcher. В настоящее время DescriptorFormatWatcher считается устарешвшим и оставлен в библиотеке только в целях совместимости. Для форматирования "на лету" рекомендуется использовать MaskFormatWatcher, т.к. он предоставляет наиболее удобный интерфейс.

Внутренне устройство обоих форматтеров отличается только механизмом создания маски. Само форматирование происходит одинаково.

DescriptorFormatWatcher (устарел)

Маска для этого форматтера создается на основе MaskDescriptor и (при необходимости) SlotsParser.

Для корректной работы DescriptorFormatWatcher требуется указать как минимум MaskDescriptor. Сделать это необходимо до установки форматтера на TextView - в конструкторе или с помощью метода DescriptorFormatWatcher#changeMask(MaskDescriptor) (с помощью этого метода можно также сменить маску после установки watcher'a).

Если указанный MaskDescriptor содержит массив слотов, то его достаточно для создания маски. Если же в декрипторе указана только raw-маска, то для создания маски потребуется предоставить SlotsParser. Сделать это можно либо в конструкторе DescriptorFormatWatcher, либо с помощью метода DescriptorFormatWatcher#setSlotsParser(SlotsParser).

Пример 1. Создание DescriptorFormatWatcher с raw-маской и отображением _ на местах для ввода:

FormatWatcher formatWatcher = new DescriptorFormatWatcher(
        new UnderscoreDigitSlotsParser(),
        MaskDescriptor.ofRawMask("___ ___ ___", true).withShowingEmptySlots(true)
);
formatWatcher.installOn(editText);

editText.setText("123456");
System.out.println(editText.getText());    // 123 456 ___

editText.getText().insert(0, "789");
System.out.println(editText.getText());    // 789 123 456

MaskFormatWatcher

С появлением в версии 1.1 конструктора копирования для MaskImpl появилась возможность не использовать MaskDescriptor для корректной работы форматтера. Новый класс MaskFormatWatcher позволяет пересоздавать маску на основе уже существующей, что дклает работу форматтера более явной. Для работы MaskFormatWatcher необходимо вручную создать маску (см. Создание маски) и передать ее форматтеру.

Пример 2. Создание MaskFormatWatcher с raw-маской и отображением _ на местах для ввода:

Slot[] slots = new UnderscoreDigitSlotsParser().parseSlots("___ ___ ___");
Mask mask = MaskImpl.createTerminated(slots);
mask.setShowingEmptySlots(true);

FormatWatcher formatWatcher = new MaskFormatWatcher(mask);

formatWatcher.installOn(editText);
editText.setText("123456");
System.out.println(editText.getText());    // 123 456 ___

editText.getText().insert(0, "789");
System.out.println(editText.getText());    // 789 123 456