Поиск по этому блогу

суббота, 21 февраля 2015 г.

Фильтр на поле для ввода мобильного номера

Интересная штука фильтры, я вот задавался целью добавить фильтр на ввод мобильного телефона, начал гуглить, а гугл то показывает все кроме того что мне надо. Перепробовал кучу вариантов, в итоге нашел хороший вариант, спасибо одному человеку на форуме, он как то спрашивал там и ему никто не помог в итоге он сам нашел решение и написал ответ на форуме.

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

В общем вот как будет выглядеть код нашего слушателя.

UsPhoneNumberFormatter.java
import java.lang.ref.WeakReference;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

public class UsPhoneNumberFormatter implements TextWatcher {

    private boolean mFormatting;
    private boolean clearFlag;
    private int mLastStartLocation;
    private String mLastBeforeText;
    private WeakReference<EditText> mWeakEditText;

    public UsPhoneNumberFormatter(WeakReference<EditText> weakEditText) {
        this.mWeakEditText = weakEditText;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (after == 0 && s.toString().equals("380 ")) {
            clearFlag = true;
        }
        mLastStartLocation = start;
        mLastBeforeText = s.toString();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) { }

    @Override
    public void afterTextChanged(Editable s) {
        if (!mFormatting) {
            mFormatting = true;
            int curPos = mLastStartLocation;
            String beforeValue = mLastBeforeText;
            String currentValue = s.toString();
            String formattedValue = formatUsNumber(s);
            if (currentValue.length() > beforeValue.length()) {
                int setCusorPos = formattedValue.length()
                        - (beforeValue.length() - curPos);
                mWeakEditText.get().setSelection(setCusorPos < 0 ? 0 : setCusorPos);
            } else {
                int setCusorPos = formattedValue.length()
                        - (currentValue.length() - curPos);
                if(setCusorPos > 0 && !Character.isDigit(formattedValue.charAt(setCusorPos - 1))){
                    setCusorPos--;
                }
                mWeakEditText.get().setSelection(setCusorPos < 0 ? 0 : setCusorPos);
            }
            mFormatting = false;
        }
    }

    private String formatUsNumber(Editable text) {
        StringBuilder formattedString = new StringBuilder();
        // удаляем все кроме цифр
        int p = 0;
        while (p < text.length()) {
            char ch = text.charAt(p);
            if (!Character.isDigit(ch)) {
                text.delete(p, p + 1);
            } else {
                p++;
            }
        }
        //оставляем ток цифры
        String allDigitString = text.toString();

        int totalDigitCount = allDigitString.length();

        if (totalDigitCount == 0
                || (totalDigitCount > 12 && !allDigitString.startsWith("380"))
                || totalDigitCount > 13) {
            text.clear();
            text.append(allDigitString);
            return allDigitString;
        }
        int alreadyPlacedDigitCount = 0;
        //если нажали бекспейс стираем все
        if (allDigitString.equals("380") && clearFlag) {
            text.clear();
            clearFlag = false;
            return "";
        }
        if (allDigitString.startsWith("380")) {
            formattedString.append("380 ");
            alreadyPlacedDigitCount+=3;
        }
        // Первые 3 цифры"380" должен быть заключен в скобки "()"
        if (totalDigitCount - alreadyPlacedDigitCount > 2 && totalDigitCount > 3) {
            formattedString.append("("
                    + allDigitString.substring(alreadyPlacedDigitCount,
                            alreadyPlacedDigitCount + 2) + ") ");
            alreadyPlacedDigitCount += 2;
        }
        // Вставляем "-" после 3 цифр
        if (totalDigitCount - alreadyPlacedDigitCount > 3) {
            formattedString.append(allDigitString.substring(
                    alreadyPlacedDigitCount, alreadyPlacedDigitCount + 3)
                    + "-");
            alreadyPlacedDigitCount += 3;
        }
        // Вставляем "-" после 10 чисел
        if (totalDigitCount - alreadyPlacedDigitCount > 2 && totalDigitCount > 10) {
            formattedString.append(allDigitString.substring(
                    alreadyPlacedDigitCount, alreadyPlacedDigitCount + 2)
                    + "-");
            alreadyPlacedDigitCount += 2;
        }
        
        if (totalDigitCount > alreadyPlacedDigitCount) {
            formattedString.append(allDigitString
                    .substring(alreadyPlacedDigitCount));
        }

        text.clear();
        text.append(formattedString.toString());
        return formattedString.toString();
    }
}

Тут как я и рассказывал выше мы задаем разные правила которым он должен следовать, и дальше просто проверяем каждый введенный символ пользователем и сравниваем подходит он нам или нет в данном контексте.

А для того что бы его вызвать нам нужно зарегистрировать слушателя в нашей активити или фрагменте и задать нашему едит тексту textChangeListenr'a, и все, наш класс будет следить за введенным текстом. Это делается вот так:

SomeActivity.java
UsPhoneNumberFormatter addLineNumberFormatter = new UsPhoneNumberFormatter(
                        new WeakReference<EditText>(phoneNamber));
EditText phoneNamber = (EditText) findViewById(R.id.edittext3);
phoneNamber.addTextChangedListener(addLineNumberFormatter);

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