android.text.InputFilter

Here are the examples of the java api android.text.InputFilter taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

111 Examples 7

19 Source : CharacterHandler.java
with Apache License 2.0
from Zweihui

/**
 * ================================================
 * 处理字符串的工具类
 * <p>
 * Created by JessYan on 2016/3/16
 * <a href="mailto:[email protected]">Contact me</a>
 * <a href="https://github.com/JessYanCoding">Follow me</a>
 * ================================================
 */
public clreplaced CharacterHandler {

    private CharacterHandler() {
        throw new IllegalStateException("you can't instantiate me!");
    }

    public static final InputFilter emojiFilter = new // emoji过滤器
    InputFilter() {

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Matcher emojiMatcher = emoji.matcher(source);
            if (emojiMatcher.find()) {
                return "";
            }
            return null;
        }
    };

    /**
     * 字符串转换成十六进制字符串
     *
     * @return String 每个Byte之间空格分隔,如: [61 6C 6B]
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }

    /**
     * json 格式化
     *
     * @param json
     * @return
     */
    public static String jsonFormat(String json) {
        if (TextUtils.isEmpty(json)) {
            return "Empty/Null json content";
        }
        String message;
        try {
            json = json.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                message = jsonObject.toString(4);
            } else if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                message = jsonArray.toString(4);
            } else {
                message = json;
            }
        } catch (JSONException e) {
            message = json;
        }
        return message;
    }

    /**
     * xml 格式化
     *
     * @param xml
     * @return
     */
    public static String xmlFormat(String xml) {
        if (TextUtils.isEmpty(xml)) {
            return "Empty/Null xml content";
        }
        String message;
        try {
            Source xmlInput = new StreamSource(new StringReader(xml));
            StreamResult xmlOutput = new StreamResult(new StringWriter());
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.transform(xmlInput, xmlOutput);
            message = xmlOutput.getWriter().toString().replaceFirst(">", ">\n");
        } catch (TransformerException e) {
            message = xml;
        }
        return message;
    }
}

19 Source : EditSpinner.java
with Apache License 2.0
from xuexiangjys

/**
 * 设置输入框的最大字符长度
 *
 * @param maxLength
 * @return
 */
public EditSpinner setMaxLength(int maxLength) {
    if (mEditText != null && maxLength > 0) {
        InputFilter[] filters = { new InputFilter.LengthFilter(maxLength) };
        mEditText.setFilters(filters);
    }
    return this;
}

19 Source : CharacterHandler.java
with Apache License 2.0
from xiaobailong24

/**
 * @author xiaobailong24
 * @date 2016/3/16
 * 处理字符串的工具类
 */
public clreplaced CharacterHandler {

    private CharacterHandler() {
        throw new IllegalStateException("you can't instantiate me!");
    }

    /**
     * emoji 过滤器
     */
    public static final InputFilter emojiFilter = new InputFilter() {

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Matcher emojiMatcher = emoji.matcher(source);
            if (emojiMatcher.find()) {
                return "";
            }
            return null;
        }
    };

    /**
     * 字符串转换成十六进制字符串
     *
     * @return String 每个Byte之间空格分隔,如: [61 6C 6B]
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }

    /**
     * json 格式化
     *
     * @param json 要格式化的 json 字符串
     * @return 格式化后的新字符串
     */
    public static String jsonFormat(String json) {
        if (TextUtils.isEmpty(json)) {
            return "Empty/Null json content";
        }
        String message;
        try {
            json = json.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                message = jsonObject.toString(4);
            } else if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                message = jsonArray.toString(4);
            } else {
                message = json;
            }
        } catch (JSONException e) {
            message = json;
        }
        return message;
    }

    /**
     * xml 格式化
     *
     * @param xml 要格式化的 xml 字符串
     * @return 格式化后的新字符串
     */
    public static String xmlFormat(String xml) {
        if (TextUtils.isEmpty(xml)) {
            return "Empty/Null xml content";
        }
        String message;
        try {
            Source xmlInput = new StreamSource(new StringReader(xml));
            StreamResult xmlOutput = new StreamResult(new StringWriter());
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.transform(xmlInput, xmlOutput);
            message = xmlOutput.getWriter().toString().replaceFirst(">", ">\n");
        } catch (TransformerException e) {
            message = xml;
        }
        return message;
    }
}

19 Source : CharacterHandler.java
with Apache License 2.0
from xiaobailong24

/**
 * Created by zhiyicx on 2016/3/16.
 */
public clreplaced CharacterHandler {

    private CharacterHandler() {
    }

    public static final InputFilter emojiFilter = new // emoji过滤器
    InputFilter() {

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Matcher emojiMatcher = emoji.matcher(source);
            if (emojiMatcher.find()) {
                return "";
            }
            return null;
        }
    };

    /**
     * 字符串转换成十六进制字符串
     *
     * @return String 每个Byte之间空格分隔,如: [61 6C 6B]
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }

    /**
     * json 格式化
     *
     * @param json
     * @return
     */
    public static String jsonFormat(String json) {
        if (TextUtils.isEmpty(json)) {
            return "Empty/Null json content";
        }
        String message;
        try {
            json = json.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                message = jsonObject.toString(4);
            } else if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                message = jsonArray.toString(4);
            } else {
                message = json;
            }
        } catch (JSONException e) {
            message = json;
        }
        return message;
    }

    /**
     * xml 格式化
     *
     * @param xml
     * @return
     */
    public static String xmlFormat(String xml) {
        if (TextUtils.isEmpty(xml)) {
            return "Empty/Null xml content";
        }
        String message;
        try {
            Source xmlInput = new StreamSource(new StringReader(xml));
            StreamResult xmlOutput = new StreamResult(new StringWriter());
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.transform(xmlInput, xmlOutput);
            message = xmlOutput.getWriter().toString().replaceFirst(">", ">\n");
        } catch (TransformerException e) {
            message = xml;
        }
        return message;
    }
}

19 Source : TEditText.java
with Apache License 2.0
from triline3

@Override
public void setFilters(InputFilter[] filters) {
    super.setFilters(filters);
}

19 Source : PhotoViewerCaptionEnterView.java
with GNU General Public License v2.0
from TelePlusDev

public void setFieldText(CharSequence text) {
    if (messageEditText == null) {
        return;
    }
    messageEditText.setText(text);
    messageEditText.setSelection(messageEditText.getText().length());
    if (delegate != null) {
        delegate.onTextChanged(messageEditText.getText());
    }
    int old = captionMaxLength;
    captionMaxLength = MessagesController.getInstance(UserConfig.selectedAccount).maxCaptionLength;
    if (old != captionMaxLength) {
        InputFilter[] inputFilters = new InputFilter[1];
        inputFilters[0] = new InputFilter.LengthFilter(captionMaxLength);
        messageEditText.setFilters(inputFilters);
    }
}

19 Source : ChatActivity.java
with MIT License
from stytooldex

public InputFilter getInputFilterProhibitSP() {
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            StringBuffer buffer = new StringBuffer();
            for (int i = start; i < end; i++) {
                char codePoint = source.charAt(i);
                if (!getIsSP(codePoint)) {
                    buffer.append(codePoint);
                } else {
                    // ToastUtil.show("群组昵称不能含有特殊字符");
                    i++;
                    continue;
                }
            }
            if (source instanceof Spanned) {
                SpannableString sp = new SpannableString(buffer);
                TextUtils.copySpansFrom((Spanned) source, start, end, null, sp, 0);
                return sp;
            } else {
                return buffer;
            }
        }

        private boolean getIsSP(char codePoint) {
            // TODO: Implement this method
            return false;
        }
    };
    return filter;
}

19 Source : ChatActivity.java
with MIT License
from stytooldex

public InputFilter getInputFilterProhibitEmoji() {
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            StringBuffer buffer = new StringBuffer();
            for (int i = start; i < end; i++) {
                char codePoint = source.charAt(i);
                if (!getIsEmoji(codePoint)) {
                    buffer.append(codePoint);
                } else {
                    // ToastUtil.show("群组昵称不能含有第三方表情");
                    i++;
                    continue;
                }
            }
            if (source instanceof Spanned) {
                SpannableString sp = new SpannableString(buffer);
                TextUtils.copySpansFrom((Spanned) source, start, end, null, sp, 0);
                return sp;
            } else {
                return buffer;
            }
        }
    };
    return filter;
}

19 Source : DrawClickableEditText.java
with Apache License 2.0
from shenghuntianlang

public void addFilter(InputFilter filter) {
    InputFilter[] filters = getFilters();
    InputFilter[] filters2 = new InputFilter[filters.length + 1];
    for (int i = 0; i < filters.length; i++) {
        filters2[i] = filters[i];
    }
    filters2[filters.length] = filter;
    setFilters(filters2);
}

19 Source : SpannableStringBuilder.java
with GNU General Public License v3.0
from PowerExplorer

/**
 * This is the clreplaced for text whose content and markup can both be changed.
 */
public clreplaced SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable, Appendable, GraphicsOperations {

    /**
     * Create a new SpannableStringBuilder with empty contents
     */
    public SpannableStringBuilder() {
        this("");
    }

    /**
     * Create a new SpannableStringBuilder containing a copy of the
     * specified text, including its spans if any.
     */
    public SpannableStringBuilder(CharSequence text) {
        this(text, 0, text.length());
    }

    /**
     * Create a new SpannableStringBuilder containing a copy of the
     * specified slice of the specified text, including its spans if any.
     */
    public SpannableStringBuilder(CharSequence text, int start, int end) {
        int srclen = end - start;
        int len = ArrayUtils.idealCharArraySize(srclen + 1);
        mText = new char[len];
        mGapStart = srclen;
        mGapLength = len - srclen;
        TextUtils.getChars(text, start, end, mText, 0);
        mSpanCount = 0;
        int alloc = ArrayUtils.idealIntArraySize(0);
        mSpans = new Object[alloc];
        mSpanStarts = new int[alloc];
        mSpanEnds = new int[alloc];
        mSpanFlags = new int[alloc];
        if (text instanceof Spanned) {
            Spanned sp = (Spanned) text;
            Object[] spans = sp.getSpans(start, end, Object.clreplaced);
            for (int i = 0; i < spans.length; i++) {
                if (spans[i] instanceof NoCopySpan) {
                    continue;
                }
                int st = sp.getSpanStart(spans[i]) - start;
                int en = sp.getSpanEnd(spans[i]) - start;
                int fl = sp.getSpanFlags(spans[i]);
                if (st < 0)
                    st = 0;
                if (st > end - start)
                    st = end - start;
                if (en < 0)
                    en = 0;
                if (en > end - start)
                    en = end - start;
                if (st <= en) {
                    setSpan(spans[i], st, en, fl);
                }
            }
        }
    }

    public static SpannableStringBuilder valueOf(CharSequence source) {
        if (source instanceof SpannableStringBuilder) {
            return (SpannableStringBuilder) source;
        } else {
            return new SpannableStringBuilder(source);
        }
    }

    /**
     * Return the char at the specified offset within the buffer.
     */
    public char charAt(int where) {
        int len = length();
        if (where < 0) {
            throw new IndexOutOfBoundsException("charAt: " + where + " < 0");
        } else if (where >= len) {
            throw new IndexOutOfBoundsException("charAt: " + where + " >= length " + len);
        }
        if (where >= mGapStart)
            return mText[where + mGapLength];
        else
            return mText[where];
    }

    /**
     * Return the number of chars in the buffer.
     */
    public int length() {
        return mText.length - mGapLength;
    }

    private void resizeFor(int size) {
        int newlen = ArrayUtils.idealCharArraySize(size + 1);
        // Jota Text Editor
        if (size > 512 * 1024) {
            newlen = size + 128 * 1024;
        }
        char[] newtext = new char[newlen];
        int after = mText.length - (mGapStart + mGapLength);
        System.arraycopy(mText, 0, newtext, 0, mGapStart);
        System.arraycopy(mText, mText.length - after, newtext, newlen - after, after);
        for (int i = 0; i < mSpanCount; i++) {
            if (mSpanStarts[i] > mGapStart)
                mSpanStarts[i] += newlen - mText.length;
            if (mSpanEnds[i] > mGapStart)
                mSpanEnds[i] += newlen - mText.length;
        }
        int oldlen = mText.length;
        mText = newtext;
        mGapLength += mText.length - oldlen;
        if (mGapLength < 1)
            new Exception("mGapLength < 1").printStackTrace();
    }

    private void moveGapTo(int where) {
        if (where == mGapStart)
            return;
        boolean atend = (where == length());
        if (where < mGapStart) {
            int overlap = mGapStart - where;
            System.arraycopy(mText, where, mText, mGapStart + mGapLength - overlap, overlap);
        } else /* where > mGapStart */
        {
            int overlap = where - mGapStart;
            System.arraycopy(mText, where + mGapLength - overlap, mText, mGapStart, overlap);
        }
        // XXX be more clever
        for (int i = 0; i < mSpanCount; i++) {
            int start = mSpanStarts[i];
            int end = mSpanEnds[i];
            if (start > mGapStart)
                start -= mGapLength;
            if (start > where)
                start += mGapLength;
            else if (start == where) {
                int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
                if (flag == POINT || (atend && flag == PARAGRAPH))
                    start += mGapLength;
            }
            if (end > mGapStart)
                end -= mGapLength;
            if (end > where)
                end += mGapLength;
            else if (end == where) {
                int flag = (mSpanFlags[i] & END_MASK);
                if (flag == POINT || (atend && flag == PARAGRAPH))
                    end += mGapLength;
            }
            mSpanStarts[i] = start;
            mSpanEnds[i] = end;
        }
        mGapStart = where;
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder insert(int where, CharSequence tb, int start, int end) {
        return replace(where, where, tb, start, end);
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder insert(int where, CharSequence tb) {
        return replace(where, where, tb, 0, tb.length());
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder delete(int start, int end) {
        SpannableStringBuilder ret = replace(start, end, "", 0, 0);
        if (mGapLength > 2 * length())
            resizeFor(length());
        // == this
        return ret;
    }

    // Doreplacedentation from interface
    public void clear() {
        replace(0, length(), "", 0, 0);
    }

    // Doreplacedentation from interface
    public void clearSpans() {
        for (int i = mSpanCount - 1; i >= 0; i--) {
            Object what = mSpans[i];
            int ostart = mSpanStarts[i];
            int oend = mSpanEnds[i];
            if (ostart > mGapStart)
                ostart -= mGapLength;
            if (oend > mGapStart)
                oend -= mGapLength;
            mSpanCount = i;
            mSpans[i] = null;
            sendSpanRemoved(what, ostart, oend);
        }
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder append(CharSequence text) {
        int length = length();
        return replace(length, length, text, 0, text.length());
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder append(CharSequence text, int start, int end) {
        int length = length();
        return replace(length, length, text, start, end);
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder append(char text) {
        return append(String.valueOf(text));
    }

    private int change(int start, int end, CharSequence tb, int tbstart, int tbend) {
        return change(true, start, end, tb, tbstart, tbend);
    }

    private int change(boolean notify, int start, int end, CharSequence tb, int tbstart, int tbend) {
        checkRange("replace", start, end);
        int ret = tbend - tbstart;
        Texreplacedcher[] recipients = null;
        if (notify)
            recipients = sendTextWillChange(start, end - start, tbend - tbstart);
        for (int i = mSpanCount - 1; i >= 0; i--) {
            if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
                int st = mSpanStarts[i];
                if (st > mGapStart)
                    st -= mGapLength;
                int en = mSpanEnds[i];
                if (en > mGapStart)
                    en -= mGapLength;
                int ost = st;
                int oen = en;
                int clen = length();
                if (st > start && st <= end) {
                    for (st = end; st < clen; st++) if (st > end && charAt(st - 1) == '\n')
                        break;
                }
                if (en > start && en <= end) {
                    for (en = end; en < clen; en++) if (en > end && charAt(en - 1) == '\n')
                        break;
                }
                if (st != ost || en != oen)
                    setSpan(mSpans[i], st, en, mSpanFlags[i]);
            }
        }
        moveGapTo(end);
        if (tbend - tbstart >= mGapLength + (end - start))
            resizeFor(mText.length - mGapLength + tbend - tbstart - (end - start));
        mGapStart += tbend - tbstart - (end - start);
        mGapLength -= tbend - tbstart - (end - start);
        if (mGapLength < 1)
            new Exception("mGapLength < 1").printStackTrace();
        TextUtils.getChars(tb, tbstart, tbend, mText, start);
        if (tb instanceof Spanned) {
            Spanned sp = (Spanned) tb;
            Object[] spans = sp.getSpans(tbstart, tbend, Object.clreplaced);
            for (int i = 0; i < spans.length; i++) {
                int st = sp.getSpanStart(spans[i]);
                int en = sp.getSpanEnd(spans[i]);
                if (st < tbstart)
                    st = tbstart;
                if (en > tbend)
                    en = tbend;
                if (getSpanStart(spans[i]) < 0) {
                    setSpan(false, spans[i], st - tbstart + start, en - tbstart + start, sp.getSpanFlags(spans[i]));
                }
            }
        }
        // no need for span fixup on pure insertion
        if (tbend > tbstart && end - start == 0) {
            if (notify) {
                sendTextChange(recipients, start, end - start, tbend - tbstart);
                sendTextHasChanged(recipients);
            }
            return ret;
        }
        boolean atend = (mGapStart + mGapLength == mText.length);
        for (int i = mSpanCount - 1; i >= 0; i--) {
            if (mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength) {
                int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
                if (flag == POINT || (flag == PARAGRAPH && atend))
                    mSpanStarts[i] = mGapStart + mGapLength;
                else
                    mSpanStarts[i] = start;
            }
            if (mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
                int flag = (mSpanFlags[i] & END_MASK);
                if (flag == POINT || (flag == PARAGRAPH && atend))
                    mSpanEnds[i] = mGapStart + mGapLength;
                else
                    mSpanEnds[i] = start;
            }
            // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
            // XXX send notification on removal
            if (mSpanEnds[i] < mSpanStarts[i]) {
                System.arraycopy(mSpans, i + 1, mSpans, i, mSpanCount - (i + 1));
                System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, mSpanCount - (i + 1));
                System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, mSpanCount - (i + 1));
                System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, mSpanCount - (i + 1));
                mSpanCount--;
            }
        }
        if (notify) {
            sendTextChange(recipients, start, end - start, tbend - tbstart);
            sendTextHasChanged(recipients);
        }
        return ret;
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder replace(int start, int end, CharSequence tb) {
        return replace(start, end, tb, 0, tb.length());
    }

    // Doreplacedentation from interface
    public SpannableStringBuilder replace(final int start, final int end, CharSequence tb, int tbstart, int tbend) {
        int filtercount = mFilters.length;
        for (int i = 0; i < filtercount; i++) {
            CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end);
            if (repl != null) {
                tb = repl;
                tbstart = 0;
                tbend = repl.length();
            }
        }
        if (end == start && tbstart == tbend) {
            return this;
        }
        if (end == start || tbstart == tbend) {
            change(start, end, tb, tbstart, tbend);
        } else {
            int selstart = Selection.getSelectionStart(this);
            int selend = Selection.getSelectionEnd(this);
            // XXX just make the span fixups in change() do the right thing
            // instead of this madness!
            checkRange("replace", start, end);
            moveGapTo(end);
            Texreplacedcher[] recipients;
            recipients = sendTextWillChange(start, end - start, tbend - tbstart);
            int origlen = end - start;
            if (mGapLength < 2)
                resizeFor(length() + 1);
            for (int i = mSpanCount - 1; i >= 0; i--) {
                if (mSpanStarts[i] == mGapStart)
                    mSpanStarts[i]++;
                if (mSpanEnds[i] == mGapStart)
                    mSpanEnds[i]++;
            }
            mText[mGapStart] = ' ';
            mGapStart++;
            mGapLength--;
            if (mGapLength < 1)
                new Exception("mGapLength < 1").printStackTrace();
            int oldlen = (end + 1) - start;
            int inserted = change(false, start + 1, start + 1, tb, tbstart, tbend);
            change(false, start, start + 1, "", 0, 0);
            change(false, start + inserted, start + inserted + oldlen - 1, "", 0, 0);
            /*
             * Special case to keep the cursor in the same position
             * if it was somewhere in the middle of the replaced region.
             * If it was at the start or the end or crossing the whole
             * replacement, it should already be where it belongs.
             * TODO: Is there some more general mechanism that could
             * accomplish this?
             */
            if (selstart > start && selstart < end) {
                long off = selstart - start;
                off = off * inserted / (end - start);
                selstart = (int) off + start;
                setSpan(false, Selection.SELECTION_START, selstart, selstart, Spanned.SPAN_POINT_POINT);
            }
            if (selend > start && selend < end) {
                long off = selend - start;
                off = off * inserted / (end - start);
                selend = (int) off + start;
                setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT);
            }
            sendTextChange(recipients, start, origlen, inserted);
            sendTextHasChanged(recipients);
        }
        return this;
    }

    /**
     * Mark the specified range of text with the specified object.
     * The flags determine how the span will behave when text is
     * inserted at the start or end of the span's range.
     */
    public void setSpan(Object what, int start, int end, int flags) {
        setSpan(true, what, start, end, flags);
    }

    private void setSpan(boolean send, Object what, int start, int end, int flags) {
        int nstart = start;
        int nend = end;
        checkRange("setSpan", start, end);
        if ((flags & START_MASK) == (PARAGRAPH << START_SHIFT)) {
            if (start != 0 && start != length()) {
                char c = charAt(start - 1);
                if (c != '\n')
                    throw new RuntimeException("PARAGRAPH span must start at paragraph boundary");
            }
        }
        if ((flags & END_MASK) == PARAGRAPH) {
            if (end != 0 && end != length()) {
                char c = charAt(end - 1);
                if (c != '\n')
                    throw new RuntimeException("PARAGRAPH span must end at paragraph boundary");
            }
        }
        if (start > mGapStart)
            start += mGapLength;
        else if (start == mGapStart) {
            int flag = (flags & START_MASK) >> START_SHIFT;
            if (flag == POINT || (flag == PARAGRAPH && start == length()))
                start += mGapLength;
        }
        if (end > mGapStart)
            end += mGapLength;
        else if (end == mGapStart) {
            int flag = (flags & END_MASK);
            if (flag == POINT || (flag == PARAGRAPH && end == length()))
                end += mGapLength;
        }
        int count = mSpanCount;
        Object[] spans = mSpans;
        for (int i = 0; i < count; i++) {
            if (spans[i] == what) {
                int ostart = mSpanStarts[i];
                int oend = mSpanEnds[i];
                if (ostart > mGapStart)
                    ostart -= mGapLength;
                if (oend > mGapStart)
                    oend -= mGapLength;
                mSpanStarts[i] = start;
                mSpanEnds[i] = end;
                mSpanFlags[i] = flags;
                if (send)
                    sendSpanChanged(what, ostart, oend, nstart, nend);
                return;
            }
        }
        if (mSpanCount + 1 >= mSpans.length) {
            int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
            Object[] newspans = new Object[newsize];
            int[] newspanstarts = new int[newsize];
            int[] newspanends = new int[newsize];
            int[] newspanflags = new int[newsize];
            System.arraycopy(mSpans, 0, newspans, 0, mSpanCount);
            System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount);
            System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount);
            System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount);
            mSpans = newspans;
            mSpanStarts = newspanstarts;
            mSpanEnds = newspanends;
            mSpanFlags = newspanflags;
        }
        mSpans[mSpanCount] = what;
        mSpanStarts[mSpanCount] = start;
        mSpanEnds[mSpanCount] = end;
        mSpanFlags[mSpanCount] = flags;
        mSpanCount++;
        if (send)
            sendSpanAdded(what, nstart, nend);
    }

    /**
     * Remove the specified markup object from the buffer.
     */
    public void removeSpan(Object what) {
        for (int i = mSpanCount - 1; i >= 0; i--) {
            if (mSpans[i] == what) {
                int ostart = mSpanStarts[i];
                int oend = mSpanEnds[i];
                if (ostart > mGapStart)
                    ostart -= mGapLength;
                if (oend > mGapStart)
                    oend -= mGapLength;
                int count = mSpanCount - (i + 1);
                System.arraycopy(mSpans, i + 1, mSpans, i, count);
                System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
                System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
                System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
                mSpanCount--;
                mSpans[mSpanCount] = null;
                sendSpanRemoved(what, ostart, oend);
                return;
            }
        }
    }

    /**
     * Return the buffer offset of the beginning of the specified
     * markup object, or -1 if it is not attached to this buffer.
     */
    public int getSpanStart(Object what) {
        int count = mSpanCount;
        Object[] spans = mSpans;
        for (int i = count - 1; i >= 0; i--) {
            if (spans[i] == what) {
                int where = mSpanStarts[i];
                if (where > mGapStart)
                    where -= mGapLength;
                return where;
            }
        }
        return -1;
    }

    /**
     * Return the buffer offset of the end of the specified
     * markup object, or -1 if it is not attached to this buffer.
     */
    public int getSpanEnd(Object what) {
        int count = mSpanCount;
        Object[] spans = mSpans;
        for (int i = count - 1; i >= 0; i--) {
            if (spans[i] == what) {
                int where = mSpanEnds[i];
                if (where > mGapStart)
                    where -= mGapLength;
                return where;
            }
        }
        return -1;
    }

    /**
     * Return the flags of the end of the specified
     * markup object, or 0 if it is not attached to this buffer.
     */
    public int getSpanFlags(Object what) {
        int count = mSpanCount;
        Object[] spans = mSpans;
        for (int i = count - 1; i >= 0; i--) {
            if (spans[i] == what) {
                return mSpanFlags[i];
            }
        }
        return 0;
    }

    /**
     * Return an array of the spans of the specified type that overlap
     * the specified range of the buffer.  The kind may be Object.clreplaced to get
     * a list of all the spans regardless of type.
     */
    public <T> T[] getSpans(int queryStart, int queryEnd, Clreplaced<T> kind) {
        int spanCount = mSpanCount;
        Object[] spans = mSpans;
        int[] starts = mSpanStarts;
        int[] ends = mSpanEnds;
        int[] flags = mSpanFlags;
        int gapstart = mGapStart;
        int gaplen = mGapLength;
        int count = 0;
        Object[] ret = null;
        Object ret1 = null;
        for (int i = 0; i < spanCount; i++) {
            int spanStart = starts[i];
            int spanEnd = ends[i];
            if (spanStart > gapstart) {
                spanStart -= gaplen;
            }
            if (spanEnd > gapstart) {
                spanEnd -= gaplen;
            }
            if (spanStart > queryEnd) {
                continue;
            }
            if (spanEnd < queryStart) {
                continue;
            }
            if (spanStart != spanEnd && queryStart != queryEnd) {
                if (spanStart == queryEnd)
                    continue;
                if (spanEnd == queryStart)
                    continue;
            }
            if (kind != null && !kind.isInstance(spans[i])) {
                continue;
            }
            if (count == 0) {
                ret1 = spans[i];
                count++;
            } else {
                if (count == 1) {
                    ret = (Object[]) Array.newInstance(kind, spanCount - i + 1);
                    ret[0] = ret1;
                }
                int prio = flags[i] & SPAN_PRIORITY;
                if (prio != 0) {
                    int j;
                    for (j = 0; j < count; j++) {
                        int p = getSpanFlags(ret[j]) & SPAN_PRIORITY;
                        if (prio > p) {
                            break;
                        }
                    }
                    System.arraycopy(ret, j, ret, j + 1, count - j);
                    ret[j] = spans[i];
                    count++;
                } else {
                    ret[count++] = spans[i];
                }
            }
        }
        if (count == 0) {
            return (T[]) ArrayUtils.emptyArray(kind);
        }
        if (count == 1) {
            ret = (Object[]) Array.newInstance(kind, 1);
            ret[0] = ret1;
            return (T[]) ret;
        }
        if (count == ret.length) {
            return (T[]) ret;
        }
        Object[] nret = (Object[]) Array.newInstance(kind, count);
        System.arraycopy(ret, 0, nret, 0, count);
        return (T[]) nret;
    }

    /**
     * Return the next offset after <code>start</code> but less than or
     * equal to <code>limit</code> where a span of the specified type
     * begins or ends.
     */
    public int nextSpanTransition(int start, int limit, Clreplaced kind) {
        int count = mSpanCount;
        Object[] spans = mSpans;
        int[] starts = mSpanStarts;
        int[] ends = mSpanEnds;
        int gapstart = mGapStart;
        int gaplen = mGapLength;
        if (kind == null) {
            kind = Object.clreplaced;
        }
        for (int i = 0; i < count; i++) {
            int st = starts[i];
            int en = ends[i];
            if (st > gapstart)
                st -= gaplen;
            if (en > gapstart)
                en -= gaplen;
            if (st > start && st < limit && kind.isInstance(spans[i]))
                limit = st;
            if (en > start && en < limit && kind.isInstance(spans[i]))
                limit = en;
        }
        return limit;
    }

    /**
     * Return a new CharSequence containing a copy of the specified
     * range of this buffer, including the overlapping spans.
     */
    public CharSequence subSequence(int start, int end) {
        return new SpannableStringBuilder(this, start, end);
    }

    /**
     * Copy the specified range of chars from this buffer into the
     * specified array, beginning at the specified offset.
     */
    public void getChars(int start, int end, char[] dest, int destoff) {
        checkRange("getChars", start, end);
        if (end <= mGapStart) {
            System.arraycopy(mText, start, dest, destoff, end - start);
        } else if (start >= mGapStart) {
            System.arraycopy(mText, start + mGapLength, dest, destoff, end - start);
        } else {
            System.arraycopy(mText, start, dest, destoff, mGapStart - start);
            System.arraycopy(mText, mGapStart + mGapLength, dest, destoff + (mGapStart - start), end - mGapStart);
        }
    }

    /**
     * Return a String containing a copy of the chars in this buffer.
     */
    public String toString() {
        int len = length();
        char[] buf = new char[len];
        getChars(0, len, buf, 0);
        return new String(buf);
    }

    private Texreplacedcher[] sendTextWillChange(int start, int before, int after) {
        Texreplacedcher[] recip = getSpans(start, start + before, Texreplacedcher.clreplaced);
        int n = recip.length;
        for (int i = 0; i < n; i++) {
            recip[i].beforeTextChanged(this, start, before, after);
        }
        return recip;
    }

    private void sendTextChange(Texreplacedcher[] recip, int start, int before, int after) {
        int n = recip.length;
        for (int i = 0; i < n; i++) {
            recip[i].onTextChanged(this, start, before, after);
        }
    }

    private void sendTextHasChanged(Texreplacedcher[] recip) {
        int n = recip.length;
        for (int i = 0; i < n; i++) {
            recip[i].afterTextChanged(this);
        }
    }

    private void sendSpanAdded(Object what, int start, int end) {
        SpanWatcher[] recip = getSpans(start, end, SpanWatcher.clreplaced);
        int n = recip.length;
        for (int i = 0; i < n; i++) {
            recip[i].onSpanAdded(this, what, start, end);
        }
    }

    private void sendSpanRemoved(Object what, int start, int end) {
        SpanWatcher[] recip = getSpans(start, end, SpanWatcher.clreplaced);
        int n = recip.length;
        for (int i = 0; i < n; i++) {
            recip[i].onSpanRemoved(this, what, start, end);
        }
    }

    private void sendSpanChanged(Object what, int s, int e, int st, int en) {
        SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), SpanWatcher.clreplaced);
        int n = recip.length;
        for (int i = 0; i < n; i++) {
            recip[i].onSpanChanged(this, what, s, e, st, en);
        }
    }

    private static String region(int start, int end) {
        return "(" + start + " ... " + end + ")";
    }

    private void checkRange(final String operation, int start, int end) {
        if (end < start) {
            throw new IndexOutOfBoundsException(operation + " " + region(start, end) + " has end before start");
        }
        int len = length();
        if (start > len || end > len) {
            throw new IndexOutOfBoundsException(operation + " " + region(start, end) + " ends beyond length " + len);
        }
        if (start < 0 || end < 0) {
            throw new IndexOutOfBoundsException(operation + " " + region(start, end) + " starts before 0");
        }
    }

    private boolean isprint(char c) {
        // XXX
        if (c >= ' ' && c <= '~')
            return true;
        else
            return false;
    }

    /*
    private static final int startFlag(int flag) {
        return (flag >> 4) & 0x0F;
    }

    private static final int endFlag(int flag) {
        return flag & 0x0F;
    }

    public void dump() { // XXX
        for (int i = 0; i < mGapStart; i++) {
            System.out.print('|');
            System.out.print(' ');
            System.out.print(isprint(mText[i]) ? mText[i] : '.');
            System.out.print(' ');
        }

        for (int i = mGapStart; i < mGapStart + mGapLength; i++) {
            System.out.print('|');
            System.out.print('(');
            System.out.print(isprint(mText[i]) ? mText[i] : '.');
            System.out.print(')');
        }

        for (int i = mGapStart + mGapLength; i < mText.length; i++) {
            System.out.print('|');
            System.out.print(' ');
            System.out.print(isprint(mText[i]) ? mText[i] : '.');
            System.out.print(' ');
        }

        System.out.print('\n');

        for (int i = 0; i < mText.length + 1; i++) {
            int found = 0;
            int wfound = 0;

            for (int j = 0; j < mSpanCount; j++) {
                if (mSpanStarts[j] == i) {
                    found = 1;
                    wfound = j;
                    break;
                }

                if (mSpanEnds[j] == i) {
                    found = 2;
                    wfound = j;
                    break;
                }
            }

            if (found == 1) {
                if (startFlag(mSpanFlags[wfound]) == MARK)
                    System.out.print("(   ");
                if (startFlag(mSpanFlags[wfound]) == PARAGRAPH)
                    System.out.print("<   ");
                else
                    System.out.print("[   ");
            } else if (found == 2) {
                if (endFlag(mSpanFlags[wfound]) == POINT)
                    System.out.print(")   ");
                if (endFlag(mSpanFlags[wfound]) == PARAGRAPH)
                    System.out.print(">   ");
                else
                    System.out.print("]   ");
            } else {
                System.out.print("    ");
            }
        }

        System.out.print("\n");
    }
*/
    /**
     * Don't call this yourself -- exists for Canvas to use internally.
     * {@hide}
     */
    @Override
    public void drawText(Canvas c, int start, int end, float x, float y, Paint p) {
        checkRange("drawText", start, end);
        // if (end <= mGapStart) {
        // c.drawText(mText, start, end - start, x, y, newp);
        // } else if (start >= mGapStart) {
        // c.drawText(mText, start + mGapLength, end - start, x, y, p);
        // } else {
        char[] buf = TextUtils.obtain(end - start);
        getChars(start, end, buf, 0);
        c.drawText(buf, 0, end - start, x, y, p);
        TextUtils.recycle(buf);
    // }
    }

    @Override
    public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, Paint p) {
    }

    /**
     * Don't call this yourself -- exists for Paint to use internally.
     * {@hide}
     */
    @Override
    public float measureText(int start, int end, Paint p) {
        checkRange("measureText", start, end);
        float ret;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            if (end <= mGapStart) {
                ret = p.measureText(mText, start, end - start);
            } else if (start >= mGapStart) {
                ret = p.measureText(mText, start + mGapLength, end - start);
            } else {
                char[] buf = TextUtils.obtain(end - start);
                getChars(start, end, buf, 0);
                ret = p.measureText(buf, 0, end - start);
                TextUtils.recycle(buf);
            }
        } else {
            char[] buf = TextUtils.obtain(end - start);
            getChars(start, end, buf, 0);
            ret = p.measureText(buf, 0, end - start);
            TextUtils.recycle(buf);
        }
        return ret;
    }

    /**
     * Don't call this yourself -- exists for Paint to use internally.
     * {@hide}
     */
    @Override
    public int getTextWidths(int start, int end, float[] widths, Paint p) {
        checkRange("getTextWidths", start, end);
        int ret;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            if (end <= mGapStart) {
                ret = p.getTextWidths(mText, start, end - start, widths);
            } else if (start >= mGapStart) {
                ret = p.getTextWidths(mText, start + mGapLength, end - start, widths);
            } else {
                char[] buf = TextUtils.obtain(end - start);
                getChars(start, end, buf, 0);
                ret = p.getTextWidths(buf, 0, end - start, widths);
                TextUtils.recycle(buf);
            }
        } else {
            char[] buf = TextUtils.obtain(end - start);
            getChars(start, end, buf, 0);
            ret = p.getTextWidths(buf, 0, end - start, widths);
            TextUtils.recycle(buf);
        }
        return ret;
    }

    @Override
    public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, boolean isRtl, float[] advances, int advancesIndex, Paint paint) {
        return 0;
    }

    // @Override
    // public void drawTextRun(Canvas c, int start, int end,
    // int contextStart, int contextEnd,
    // float x, float y, int flags, Paint p) {
    // checkRange("drawTextRun", start, end);
    // /*
    // int contextLen = contextEnd - contextStart;
    // int len = end - start;
    // if (contextEnd <= mGapStart) {
    // c.drawTextRun(mText, start, len, contextStart, contextLen, x, y, flags, p);
    // } else if (contextStart >= mGapStart) {
    // c.drawTextRun(mText, start + mGapLength, len, contextStart + mGapLength,
    // contextLen, x, y, flags, p);
    // } else {
    // char[] buf = TextUtils.obtain(contextLen);
    // getChars(contextStart, contextEnd, buf, 0);
    // c.drawTextRun(buf, start - contextStart, len, 0, contextLen, x, y, flags, p);
    // TextUtils.recycle(buf);
    // }
    // */
    // }
    // @Override
    // public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags,
    // float[] advances, int advancesPos, Paint p) {
    // 
    // float ret=0;
    // /*
    // int contextLen = contextEnd - contextStart;
    // int len = end - start;
    // 
    // if (end <= mGapStart) {
    // ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen,
    // flags, advances, advancesPos);
    // } else if (start >= mGapStart) {
    // ret = p.getTextRunAdvances(mText, start + mGapLength, len,
    // contextStart + mGapLength, contextLen, flags, advances, advancesPos);
    // } else {
    // char[] buf = TextUtils.obtain(contextLen);
    // getChars(contextStart, contextEnd, buf, 0);
    // ret = p.getTextRunAdvances(buf, start - contextStart, len,
    // 0, contextLen, flags, advances, advancesPos);
    // TextUtils.recycle(buf);
    // }
    // */
    // return ret;
    // }
    // @Override
    // public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags,
    // float[] advances, int advancesPos, Paint p, int reserved , int a) {
    // 
    // float ret=0;
    // /*
    // int contextLen = contextEnd - contextStart;
    // int len = end - start;
    // 
    // if (end <= mGapStart) {
    // ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen,
    // flags, advances, advancesPos, reserved);
    // } else if (start >= mGapStart) {
    // ret = p.getTextRunAdvances(mText, start + mGapLength, len,
    // contextStart + mGapLength, contextLen, flags, advances, advancesPos, reserved);
    // } else {
    // char[] buf = TextUtils.obtain(contextLen);
    // getChars(contextStart, contextEnd, buf, 0);
    // ret = p.getTextRunAdvances(buf, start - contextStart, len,
    // 0, contextLen, flags, advances, advancesPos, reserved);
    // TextUtils.recycle(buf);
    // }
    // */
    // return ret;
    // }
    @Override
    public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset, int cursorOpt, Paint p) {
        int ret = 0;
        /*
        int contextLen = contextEnd - contextStart;
        if (contextEnd <= mGapStart) {
            ret = p.getTextRunCursor(mText, contextStart, contextLen,
                    flags, offset, cursorOpt);
        } else if (contextStart >= mGapStart) {
            ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen,
                    flags, offset + mGapLength, cursorOpt) - mGapLength;
        } else {
            char[] buf = TextUtils.obtain(contextLen);
            getChars(contextStart, contextEnd, buf, 0);
            ret = p.getTextRunCursor(buf, 0, contextLen,
                    flags, offset - contextStart, cursorOpt) + contextStart;
            TextUtils.recycle(buf);
        }
*/
        return ret;
    }

    // Doreplacedentation from interface
    public void setFilters(InputFilter[] filters) {
        if (filters == null) {
            throw new IllegalArgumentException();
        }
        mFilters = filters;
    }

    // Doreplacedentation from interface
    public InputFilter[] getFilters() {
        return mFilters;
    }

    public int findBlockStart(int start) {
        final char[] text = mText;
        final int gapStart = mGapStart;
        final int gapLength = mGapLength;
        if (length() <= start) {
            return start;
        }
        for (; start > 0; start--) {
            int where = start - 1;
            char c = (where >= gapStart) ? text[where + gapLength] : text[where];
            if (c == '\n') {
                break;
            }
        }
        return start;
    }

    public int findBlockEnd(int end) {
        final char[] text = mText;
        final int gapStart = mGapStart;
        final int gapLength = mGapLength;
        int len = length();
        if (len <= end) {
            return end;
        }
        for (; end < len; end++) {
            int where = end;
            char c = (where >= gapStart) ? text[where + gapLength] : text[where];
            if (c == '\n') {
                break;
            }
        }
        return end;
    }

    public int countChar(char ch, int start, int end) {
        final char[] text = mText;
        final int gapStart = mGapStart;
        final int gapLength = mGapLength;
        int res = 0;
        for (int i = start; i < gapStart && i < end; i++) {
            if (text[i] == ch)
                res++;
        }
        for (int i = gapStart + gapLength; i < end + gapLength; i++) {
            if (text[i] == ch)
                res++;
        }
        // for( int i=start;i<end ;i++){
        // char c = (i >= gapStart)? text[i + gapLength]: text[i];
        // if ( c == ch ) res++;
        // }
        return res;
    }

    private static final InputFilter[] NO_FILTERS = new InputFilter[0];

    private InputFilter[] mFilters = NO_FILTERS;

    private char[] mText;

    private int mGapStart;

    private int mGapLength;

    private Object[] mSpans;

    private int[] mSpanStarts;

    private int[] mSpanEnds;

    private int[] mSpanFlags;

    private int mSpanCount;

    private static final int MARK = 1;

    private static final int POINT = 2;

    private static final int PARAGRAPH = 3;

    private static final int START_MASK = 0xF0;

    private static final int END_MASK = 0x0F;

    private static final int START_SHIFT = 4;
}

19 Source : SpannableStringBuilder.java
with GNU General Public License v3.0
from PowerExplorer

// Doreplacedentation from interface
public void setFilters(InputFilter[] filters) {
    if (filters == null) {
        throw new IllegalArgumentException();
    }
    mFilters = filters;
}

19 Source : EditTextEmoji.java
with GNU General Public License v3.0
from NekoX-Dev

public void setFilters(InputFilter[] filters) {
    editText.setFilters(filters);
}

19 Source : HighlightEditorView.java
with GNU General Public License v3.0
from MrIkso

private void setDefaultFilters() {
    // indent filters
    final InputFilter indentFilter = (source, start, end, dest, dstart, dend) -> {
        if (mIsAutoIndent) {
            if (!(source.length() == 1 && source.charAt(0) == '\n')) {
                return null;
            }
            int startIndex = dstart - 1;
            if (startIndex < 0 || startIndex >= dest.length())
                return null;
            char ch;
            for (; startIndex >= 0; startIndex--) {
                ch = dest.charAt(startIndex);
                if (ch != '\r')
                    break;
            }
            StringBuilder indent = new StringBuilder();
            for (int i = startIndex; i >= 0; i--) {
                ch = dest.charAt(i);
                if (ch == '\n' || ch == '\r') {
                    break;
                } else if (ch == ' ' || ch == '\t') {
                    indent.append(ch);
                } else {
                    indent.setLength(0);
                }
            }
            indent.reverse();
            // bad code
            // common support java,c and c++
            // TODO: 08-Jun-18 dynamic change
            if (dend < dest.length() && dest.charAt(dend) == '}' && dstart - 1 >= 0 && dest.charAt(dstart - 1) == '{') {
                int mstart = dstart - 2;
                while (mstart >= 0 && dest.charAt(mstart) != '\n') {
                    mstart--;
                }
                String closeIndent = "";
                if (mstart >= 0) {
                    mstart++;
                    int zstart = mstart;
                    while (zstart < dest.length() && dest.charAt(zstart) == ' ') {
                        zstart++;
                    }
                    closeIndent = dest.toString().substring(mstart, zstart);
                }
                return source + (indent.toString() + "  ") + CURSOR + "\n" + closeIndent;
            }
            return "\n" + indent.toString();
        }
        return null;
    };
    // end line filter, only support \n
    InputFilter newLineFilter = (source, start, end, dest, dstart, dend) -> {
        final String s = source.toString();
        if (s.contains("\r")) {
            return s.replace("\r", "");
        }
        return null;
    };
    // bracket filter, auto add close bracket if auto pair is enable
    final InputFilter bracketFilter = (source, start, end, dest, dstart, dend) -> {
        if (mIsAutoPair) {
            if (end - start == 1 && start < source.length() && dstart < dest.length()) {
                char c = source.charAt(start);
                if (c == '(' || c == '{' || c == '[' || c == '"' || c == '\'') {
                    return addBracket(source, start);
                }
            }
        }
        return null;
    };
    setFilters(new InputFilter[] { indentFilter, newLineFilter, bracketFilter });
    // auto add bracket
    addTextChangedListener(new Texreplacedcher() {

        private int start;

        private int count;

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

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

        @Override
        public void afterTextChanged(Editable editable) {
            if (editable.length() > start && count > 1) {
                for (int i = start; i < start + count; i++) {
                    if (editable.charAt(i) == CURSOR) {
                        editable.delete(i, i + 1);
                        setSelection(start);
                        break;
                    }
                }
            }
        }
    });
}

19 Source : EditCard.java
with GNU General Public License v3.0
from Morxander

private void addMagic() {
    // Changing the icon when it's empty
    changeIcon();
    // Adding the Texreplacedcher
    addTextChangedListener(new Texreplacedcher() {

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

        @Override
        public void onTextChanged(CharSequence s, int position, int before, int action) {
            if (action == 1) {
                if (type.equals("UNKNOWN") || type.equals("Visa") || type.equals("Discover") || type.equals("JCB")) {
                    if (position == 3 || position == 8 || position == 13) {
                        if (!s.toString().endsWith("-")) {
                            append("-");
                        }
                    }
                } else if (type.equals("American_Express") || type.equals("Diners_Club")) {
                    if (position == 3 || position == 10) {
                        if (!s.toString().endsWith("-")) {
                            append("-");
                        }
                    }
                }
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
            changeIcon();
        }
    });
    // The input filters
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; ++i) {
                if (!Pattern.compile("[0-9\\-]*").matcher(String.valueOf(source)).matches()) {
                    return "";
                }
            }
            return null;
        }
    };
    // Setting the filters
    setFilters(new InputFilter[] { filter, new InputFilter.LengthFilter(19) });
}

19 Source : URegular.java
with Apache License 2.0
from KosmoSakura

/**
 * @Description 正则表达式
 * @Author Kosmos
 * @Date 2016年9月21日 17:01
 * @Email [email protected]
 * @Tip →→is:是某种特定字符
 * →→checkXX:校验类
 * →→fun:功能类
 * @Tip 2018.9.12:转录
 * @Tip 2018.12.26:重构
 * @Tip 2019.2.28:Url判断
 * @Tip 2019.3.20:新增几个正则校验
 */
public clreplaced URegular {

    private static InputFilter emojiFilter = new InputFilter() {

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Matcher emojiMatcher = emoji.matcher(source);
            if (emojiMatcher.find()) {
                return "";
            }
            return null;
        }
    };

    /**
     * @apiNote 禁止输入表情,Edt加上过滤器
     */
    public static InputFilter[] emojiFilters = { emojiFilter };

    // --check校验类-------------------------------------------------------------------------------------------------------
    /**
     * @param urls 判断字符串是否为URL(https://blog.csdn.net/bronna/article/details/77529145)
     * @return true:是URL、false:不是URL
     */
    public static boolean checkUrl(String urls) {
        boolean isUrl;
        // 判断是否是网址的正则表达式
        String regex = "(((https|http)?://)?([a-z0-9]+[.])|(www.))" + "\\w+[.|\\/]([a-z0-9]{0,})?[[.]([a-z0-9]{0,})]+((/[\\S&&[^,;\u4E00-\u9FA5]]+)+)?([.][a-z0-9]{0,}+|/?)";
        Pattern pat = Pattern.compile(regex.trim());
        Matcher mat = pat.matcher(urls.trim());
        isUrl = mat.matches();
        return isUrl;
    }

    /**
     * @apiNote true→不包含符号
     */
    public static boolean checkSymbol(String str) {
        return str.matches("^(?!_)(?!.*?_$)[a-zA-Z0-9_\\u4e00-\\u9fa5]+$");
    }

    /**
     * @apiNote true→纯汉字
     */
    public static boolean checkChineseCharacter(String str) {
        return str.matches("^[\\u4e00-\\u9fa5]+$");
    }

    /**
     * @apiNote true→ (汉字)||(字母)
     */
    public static boolean checkChineseLetter(String str) {
        return str.matches("^[a-zA-Z\\u4e00-\\u9fa5]+$");
    }

    /**
     * @apiNote true→(字母)||(数字)
     */
    public static boolean checkLetterDigit(String str) {
        return str.matches("^[A-Za-z0-9]+$");
    }

    /**
     * @apiNote true→(汉字)||(字母)||(数字)
     */
    public static boolean checkChineseLetterDigit(String str) {
        return str.matches("^[a-z0-9A-Z\\u4e00-\\u9fa5]+$");
    }

    /**
     * @apiNote true→昵称可由:(中文)||(英文)||(数字)||("_")||("-")
     */
    public static boolean checkNickName(String nickName) {
        return nickName.matches("^[_\\-a-zA-Z0-9\\u4e00-\\u9fa5]+$");
    }

    /**
     * @param digit 一位或多位0-9之间的整数
     * @apiNote true→(正整数)||(负整数)
     */
    public static boolean checkDigit(String digit) {
        return digit.matches("-?[1-9]\\d+");
    }

    /**
     * @param date 日期,格式:1992-09-03,或1992.09.03
     * @apiNote true→是上述年月日
     */
    public static boolean checkDate(String date) {
        String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";
        return Pattern.matches(regex, date);
    }

    // --check判断类-------------------------------------------------------------------------------------------------------
    /**
     * @apiNote true→是手机号码
     */
    public static boolean iskPhoneNum(String phone) {
        return phone.matches("(\\+\\d+)?1\\d{10}$");
    }

    /**
     * @apiNote true→是身份证号码
     */
    public static boolean isIdCard(String idcard) {
        return idcard.matches("[1-9]\\d{16}[a-zA-Z0-9]");
    }

    /**
     * @apiNote true→是邮箱
     */
    public static boolean isEmail(String email) {
        return email.matches("\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?");
    }

    // --Fun工具类-------------------------------------------------------------------------------------------------------
    /**
     * @apiNote 隐藏手机号中间4位
     * @eg 185****9095
     */
    public static String funHidePhone(String input) {
        return input.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }

    /**
     * @apiNote 隐藏身份证号中间N位
     * @eg 511***********5815
     */
    public static String funHideIDCard(String input) {
        return input.replaceAll("(\\d{3})\\d+(\\d{4})", "$1***********$2");
    }

    /**
     * @apiNote 隐藏银行卡号前几位
     * @eg **** **** **** **** 309
     */
    public static String funHideBankF(String input) {
        return input.replaceAll("([\\d]{4})(?=\\d)", "**** ");
    }

    /**
     * @apiNote 银行卡号每隔四位增加一个空格
     * @eg 6225 8801 3770 6868
     */
    public static String funBankCardChar(String input) {
        return input.replaceAll("([\\d]{4})(?=\\d)", "$1 ");
    }

    /**
     * @param input 6225880137706868
     * @param text  "-"
     * @apiNote 银行卡号每隔四位增加一个指定字符
     * @apiNote 银行卡号每隔四位增加一个指定字符
     * @eg 6225-8801-3770-6868
     */
    public static String funBankCardChar(String input, String text) {
        return input.replaceAll("([\\d]{4})(?=\\d)", "$1" + text);
    }

    /**
     * @param digit 1236.51634
     * @apiNote 每隔3位加一个逗号
     * 方式一:使用DecimalFormat
     * @eg 1, 236.516
     */
    public static String funformatDigit_3(double digit) {
        DecimalFormat df1 = (DecimalFormat) DecimalFormat.getInstance();
        df1.setGroupingSize(3);
        return df1.format(digit);
    }

    /**
     * @param input 1236.51634
     * @apiNote 每隔3位加一个逗号
     * 方式二:使用正则表达式
     * @eg 1, 236.5, 1634
     */
    public static String funformatDigit_3(String input) {
        String regx = "(?<=\\d)(\\d{3})";
        return input.replaceAll(regx, ",$1");
    }

    /**
     * @param digit  5556.7468f
     * @param fotmat "#,##0.00"
     * @return 5, 556.75
     * @apiNote 按照指定格式转化数字
     */
    public static String formatDigitString(double digit, String fotmat) {
        return new DecimalFormat(fotmat).format(digit);
    }
}

19 Source : CharacterHandler.java
with Apache License 2.0
from JessYanCoding

/**
 * ================================================
 * 处理字符串的工具类
 * <p>
 * Created by JessYan on 2016/3/16
 * <a href="mailto:[email protected]">Contact me</a>
 * <a href="https://github.com/JessYanCoding">Follow me</a>
 * ================================================
 */
public clreplaced CharacterHandler {

    public static final InputFilter EMOJI_FILTER = new // emoji过滤器
    InputFilter() {

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Matcher emojiMatcher = emoji.matcher(source);
            if (emojiMatcher.find()) {
                return "";
            }
            return null;
        }
    };

    private CharacterHandler() {
        throw new IllegalStateException("you can't instantiate me!");
    }

    /**
     * 字符串转换成十六进制字符串
     *
     * @return String 每个Byte之间空格分隔,如: [61 6C 6B]
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder();
        byte[] bs = str.getBytes();
        int bit;
        for (byte b : bs) {
            bit = (b & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = b & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }

    /**
     * json 格式化
     *
     * @param json
     * @return
     */
    public static String jsonFormat(String json) {
        if (TextUtils.isEmpty(json)) {
            return "Empty/Null json content";
        }
        String message;
        try {
            json = json.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                message = jsonObject.toString(4);
            } else if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                message = jsonArray.toString(4);
            } else {
                message = json;
            }
        } catch (JSONException e) {
            message = json;
        } catch (OutOfMemoryError error) {
            message = "Output omitted because of Object size";
        }
        return message;
    }

    /**
     * xml 格式化
     *
     * @param xml
     * @return
     */
    public static String xmlFormat(String xml) {
        if (TextUtils.isEmpty(xml)) {
            return "Empty/Null xml content";
        }
        String message;
        try {
            Source xmlInput = new StreamSource(new StringReader(xml));
            StreamResult xmlOutput = new StreamResult(new StringWriter());
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.transform(xmlInput, xmlOutput);
            message = xmlOutput.getWriter().toString().replaceFirst(">", ">\n");
        } catch (TransformerException e) {
            message = xml;
        }
        return message;
    }
}

19 Source : FloatingLabelEditText.java
with Apache License 2.0
from james602152002

@Override
public void setFilters(InputFilter[] filters) {
    for (int i = 0; i < filters.length; i++) {
        InputFilter filter = filters[i];
        if (filter instanceof InputFilter.LengthFilter) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                max_length = ((InputFilter.LengthFilter) filter).getMax();
            } else {
                try {
                    Field field = InputFilter.LengthFilter.clreplaced.getDeclaredField("mMax");
                    field.setAccessible(true);
                    max_length = (int) field.get(filter);
                } catch (Exception e) {
                }
            }
            break;
        }
    }
    super.setFilters(filters);
}

19 Source : ReactTextInputManager.java
with MIT License
from hellochirag

/**
 * Manages instances of TextInput.
 */
@ReactModule(name = ReactTextInputManager.REACT_CLreplaced)
public clreplaced ReactTextInputManager extends BaseViewManager<ReactEditText, LayoutShadowNode> {

    protected static final String REACT_CLreplaced = "AndroidTextInput";

    private static final int[] SPACING_TYPES = { Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM };

    private static final int FOCUS_TEXT_INPUT = 1;

    private static final int BLUR_TEXT_INPUT = 2;

    private static final int INPUT_TYPE_KEYBOARD_NUMBER_PAD = InputType.TYPE_CLreplaced_NUMBER;

    private static final int INPUT_TYPE_KEYBOARD_DECIMAL_PAD = INPUT_TYPE_KEYBOARD_NUMBER_PAD | InputType.TYPE_NUMBER_FLAG_DECIMAL;

    private static final int INPUT_TYPE_KEYBOARD_NUMBERED = INPUT_TYPE_KEYBOARD_DECIMAL_PAD | InputType.TYPE_NUMBER_FLAG_SIGNED;

    private static final int PreplacedWORD_VISIBILITY_FLAG = InputType.TYPE_TEXT_VARIATION_VISIBLE_PreplacedWORD & ~InputType.TYPE_TEXT_VARIATION_PreplacedWORD;

    private static final int KEYBOARD_TYPE_FLAGS = INPUT_TYPE_KEYBOARD_NUMBERED | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLreplaced_TEXT | InputType.TYPE_CLreplaced_PHONE | PreplacedWORD_VISIBILITY_FLAG;

    private static final String KEYBOARD_TYPE_EMAIL_ADDRESS = "email-address";

    private static final String KEYBOARD_TYPE_NUMERIC = "numeric";

    private static final String KEYBOARD_TYPE_DECIMAL_PAD = "decimal-pad";

    private static final String KEYBOARD_TYPE_NUMBER_PAD = "number-pad";

    private static final String KEYBOARD_TYPE_PHONE_PAD = "phone-pad";

    private static final String KEYBOARD_TYPE_VISIBLE_PreplacedWORD = "visible-preplacedword";

    private static final InputFilter[] EMPTY_FILTERS = new InputFilter[0];

    private static final int UNSET = -1;

    @Override
    public String getName() {
        return REACT_CLreplaced;
    }

    @Override
    public ReactEditText createViewInstance(ThemedReactContext context) {
        ReactEditText editText = new ReactEditText(context);
        int inputType = editText.getInputType();
        editText.setInputType(inputType & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE));
        editText.setReturnKeyType("done");
        editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, (int) Math.ceil(PixelUtil.toPixelFromSP(ViewDefaults.FONT_SIZE_SP)));
        return editText;
    }

    @Override
    public LayoutShadowNode createShadowNodeInstance() {
        return new ReactTextInputShadowNode();
    }

    @Override
    public Clreplaced<? extends LayoutShadowNode> getShadowNodeClreplaced() {
        return ReactTextInputShadowNode.clreplaced;
    }

    @Nullable
    @Override
    public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
        return MapBuilder.<String, Object>builder().put("topSubmitEditing", MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onSubmitEditing", "captured", "onSubmitEditingCapture"))).put("topEndEditing", MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onEndEditing", "captured", "onEndEditingCapture"))).put("topTextInput", MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onTextInput", "captured", "onTextInputCapture"))).put("topFocus", MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onFocus", "captured", "onFocusCapture"))).put("topBlur", MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onBlur", "captured", "onBlurCapture"))).put("topKeyPress", MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onKeyPress", "captured", "onKeyPressCapture"))).build();
    }

    @Nullable
    @Override
    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.<String, Object>builder().put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll")).build();
    }

    @Override
    @Nullable
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of("focusTextInput", FOCUS_TEXT_INPUT, "blurTextInput", BLUR_TEXT_INPUT);
    }

    @Override
    public void receiveCommand(ReactEditText reactEditText, int commandId, @Nullable ReadableArray args) {
        switch(commandId) {
            case FOCUS_TEXT_INPUT:
                reactEditText.requestFocusFromJS();
                break;
            case BLUR_TEXT_INPUT:
                reactEditText.clearFocusFromJS();
                break;
        }
    }

    @Override
    public void updateExtraData(ReactEditText view, Object extraData) {
        if (extraData instanceof ReactTextUpdate) {
            ReactTextUpdate update = (ReactTextUpdate) extraData;
            view.setPadding((int) update.getPaddingLeft(), (int) update.getPaddingTop(), (int) update.getPaddingRight(), (int) update.getPaddingBottom());
            if (update.containsImages()) {
                Spannable spannable = update.getText();
                TextInlineImageSpan.possiblyUpdateInlineImageSpans(spannable, view);
            }
            view.maybeSetText(update);
        }
    }

    @ReactProp(name = ViewProps.FONT_SIZE, defaultFloat = ViewDefaults.FONT_SIZE_SP)
    public void setFontSize(ReactEditText view, float fontSize) {
        view.setTextSize(TypedValue.COMPLEX_UNIT_PX, (int) Math.ceil(PixelUtil.toPixelFromSP(fontSize)));
    }

    @ReactProp(name = ViewProps.FONT_FAMILY)
    public void setFontFamily(ReactEditText view, String fontFamily) {
        int style = Typeface.NORMAL;
        if (view.getTypeface() != null) {
            style = view.getTypeface().getStyle();
        }
        Typeface newTypeface = ReactFontManager.getInstance().getTypeface(fontFamily, style, view.getContext().getreplacedets());
        view.setTypeface(newTypeface);
    }

    /**
     *  /* This code was taken from the method setFontWeight of the clreplaced ReactTextShadowNode
     *  /* TODO: Factor into a common place they can both use
     */
    @ReactProp(name = ViewProps.FONT_WEIGHT)
    public void setFontWeight(ReactEditText view, @Nullable String fontWeightString) {
        int fontWeightNumeric = fontWeightString != null ? parseNumericFontWeight(fontWeightString) : -1;
        int fontWeight = UNSET;
        if (fontWeightNumeric >= 500 || "bold".equals(fontWeightString)) {
            fontWeight = Typeface.BOLD;
        } else if ("normal".equals(fontWeightString) || (fontWeightNumeric != -1 && fontWeightNumeric < 500)) {
            fontWeight = Typeface.NORMAL;
        }
        Typeface currentTypeface = view.getTypeface();
        if (currentTypeface == null) {
            currentTypeface = Typeface.DEFAULT;
        }
        if (fontWeight != currentTypeface.getStyle()) {
            view.setTypeface(currentTypeface, fontWeight);
        }
    }

    /**
     *  /* This code was taken from the method setFontStyle of the clreplaced ReactTextShadowNode
     *  /* TODO: Factor into a common place they can both use
     */
    @ReactProp(name = ViewProps.FONT_STYLE)
    public void setFontStyle(ReactEditText view, @Nullable String fontStyleString) {
        int fontStyle = UNSET;
        if ("italic".equals(fontStyleString)) {
            fontStyle = Typeface.ITALIC;
        } else if ("normal".equals(fontStyleString)) {
            fontStyle = Typeface.NORMAL;
        }
        Typeface currentTypeface = view.getTypeface();
        if (currentTypeface == null) {
            currentTypeface = Typeface.DEFAULT;
        }
        if (fontStyle != currentTypeface.getStyle()) {
            view.setTypeface(currentTypeface, fontStyle);
        }
    }

    @ReactProp(name = "selection")
    public void setSelection(ReactEditText view, @Nullable ReadableMap selection) {
        if (selection == null) {
            return;
        }
        if (selection.hasKey("start") && selection.hasKey("end")) {
            view.setSelection(selection.getInt("start"), selection.getInt("end"));
        }
    }

    @ReactProp(name = "onSelectionChange", defaultBoolean = false)
    public void setOnSelectionChange(final ReactEditText view, boolean onSelectionChange) {
        if (onSelectionChange) {
            view.setSelectionWatcher(new ReactSelectionWatcher(view));
        } else {
            view.setSelectionWatcher(null);
        }
    }

    @ReactProp(name = "blurOnSubmit")
    public void setBlurOnSubmit(ReactEditText view, @Nullable Boolean blurOnSubmit) {
        view.setBlurOnSubmit(blurOnSubmit);
    }

    @ReactProp(name = "onContentSizeChange", defaultBoolean = false)
    public void setOnContentSizeChange(final ReactEditText view, boolean onContentSizeChange) {
        if (onContentSizeChange) {
            view.setContentSizeWatcher(new ReactContentSizeWatcher(view));
        } else {
            view.setContentSizeWatcher(null);
        }
    }

    @ReactProp(name = "onScroll", defaultBoolean = false)
    public void setOnScroll(final ReactEditText view, boolean onScroll) {
        if (onScroll) {
            view.setScrollWatcher(new ReactScrollWatcher(view));
        } else {
            view.setScrollWatcher(null);
        }
    }

    @ReactProp(name = "onKeyPress", defaultBoolean = false)
    public void setOnKeyPress(final ReactEditText view, boolean onKeyPress) {
        view.setOnKeyPress(onKeyPress);
    }

    // Sets the letter spacing as an absolute point size.
    // This extra handling, on top of what ReactBaseTextShadowNode already does, is required for the
    // correct display of spacing in placeholder (hint) text.
    @ReactProp(name = ViewProps.LETTER_SPACING, defaultFloat = 0)
    public void setLetterSpacing(ReactEditText view, float letterSpacing) {
        view.setLetterSpacingPt(letterSpacing);
    }

    @ReactProp(name = "placeholder")
    public void setPlaceholder(ReactEditText view, @Nullable String placeholder) {
        view.setHint(placeholder);
    }

    @ReactProp(name = "placeholderTextColor", customType = "Color")
    public void setPlaceholderTextColor(ReactEditText view, @Nullable Integer color) {
        if (color == null) {
            view.setHintTextColor(DefaultStyleValuesUtil.getDefaultTextColorHint(view.getContext()));
        } else {
            view.setHintTextColor(color);
        }
    }

    @ReactProp(name = "selectionColor", customType = "Color")
    public void setSelectionColor(ReactEditText view, @Nullable Integer color) {
        if (color == null) {
            view.setHighlightColor(DefaultStyleValuesUtil.getDefaultTextColorHighlight(view.getContext()));
        } else {
            view.setHighlightColor(color);
        }
        setCursorColor(view, color);
    }

    private void setCursorColor(ReactEditText view, @Nullable Integer color) {
        // Evil method that uses reflection because there is no public API to changes
        // the cursor color programmatically.
        // Based on http://stackoverflow.com/questions/25996032/how-to-change-programatically-edittext-cursor-color-in-android.
        try {
            // Get the original cursor drawable resource.
            Field cursorDrawableResField = TextView.clreplaced.getDeclaredField("mCursorDrawableRes");
            cursorDrawableResField.setAccessible(true);
            int drawableResId = cursorDrawableResField.getInt(view);
            // The view has no cursor drawable.
            if (drawableResId == 0) {
                return;
            }
            Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId);
            if (color != null) {
                drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
            }
            Drawable[] drawables = { drawable, drawable };
            // Update the current cursor drawable with the new one.
            Field editorField = TextView.clreplaced.getDeclaredField("mEditor");
            editorField.setAccessible(true);
            Object editor = editorField.get(view);
            Field cursorDrawableField = editor.getClreplaced().getDeclaredField("mCursorDrawable");
            cursorDrawableField.setAccessible(true);
            cursorDrawableField.set(editor, drawables);
        } catch (NoSuchFieldException ex) {
        // Ignore errors to avoid crashing if these private fields don't exist on modified
        // or future android versions.
        } catch (IllegalAccessException ex) {
        }
    }

    @ReactProp(name = "caretHidden", defaultBoolean = false)
    public void setCaretHidden(ReactEditText view, boolean caretHidden) {
        view.setCursorVisible(!caretHidden);
    }

    @ReactProp(name = "contextMenuHidden", defaultBoolean = false)
    public void setContextMenuHidden(ReactEditText view, boolean contextMenuHidden) {
        final boolean _contextMenuHidden = contextMenuHidden;
        view.setOnLongClickListener(new View.OnLongClickListener() {

            public boolean onLongClick(View v) {
                return _contextMenuHidden;
            }
        });
    }

    @ReactProp(name = "selectTextOnFocus", defaultBoolean = false)
    public void setSelectTextOnFocus(ReactEditText view, boolean selectTextOnFocus) {
        view.setSelectAllOnFocus(selectTextOnFocus);
    }

    @ReactProp(name = ViewProps.COLOR, customType = "Color")
    public void setColor(ReactEditText view, @Nullable Integer color) {
        if (color == null) {
            view.setTextColor(DefaultStyleValuesUtil.getDefaultTextColor(view.getContext()));
        } else {
            view.setTextColor(color);
        }
    }

    @ReactProp(name = "underlineColorAndroid", customType = "Color")
    public void setUnderlineColor(ReactEditText view, @Nullable Integer underlineColor) {
        // Drawable.mutate() can sometimes crash due to an AOSP bug:
        // See https://code.google.com/p/android/issues/detail?id=191754 for more info
        Drawable background = view.getBackground();
        Drawable drawableToMutate = background.getConstantState() != null ? background.mutate() : background;
        if (underlineColor == null) {
            drawableToMutate.clearColorFilter();
        } else {
            drawableToMutate.setColorFilter(underlineColor, PorterDuff.Mode.SRC_IN);
        }
    }

    @ReactProp(name = ViewProps.TEXT_ALIGN)
    public void setTextAlign(ReactEditText view, @Nullable String textAlign) {
        if (textAlign == null || "auto".equals(textAlign)) {
            view.setGravityHorizontal(Gravity.NO_GRAVITY);
        } else if ("left".equals(textAlign)) {
            view.setGravityHorizontal(Gravity.LEFT);
        } else if ("right".equals(textAlign)) {
            view.setGravityHorizontal(Gravity.RIGHT);
        } else if ("center".equals(textAlign)) {
            view.setGravityHorizontal(Gravity.CENTER_HORIZONTAL);
        } else if ("justify".equals(textAlign)) {
            // Fallback gracefully for cross-platform compat instead of error
            view.setGravityHorizontal(Gravity.LEFT);
        } else {
            throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign);
        }
    }

    @ReactProp(name = ViewProps.TEXT_ALIGN_VERTICAL)
    public void setTextAlignVertical(ReactEditText view, @Nullable String textAlignVertical) {
        if (textAlignVertical == null || "auto".equals(textAlignVertical)) {
            view.setGravityVertical(Gravity.NO_GRAVITY);
        } else if ("top".equals(textAlignVertical)) {
            view.setGravityVertical(Gravity.TOP);
        } else if ("bottom".equals(textAlignVertical)) {
            view.setGravityVertical(Gravity.BOTTOM);
        } else if ("center".equals(textAlignVertical)) {
            view.setGravityVertical(Gravity.CENTER_VERTICAL);
        } else {
            throw new JSApplicationIllegalArgumentException("Invalid textAlignVertical: " + textAlignVertical);
        }
    }

    @ReactProp(name = "inlineImageLeft")
    public void setInlineImageLeft(ReactEditText view, @Nullable String resource) {
        int id = ResourceDrawableIdHelper.getInstance().getResourceDrawableId(view.getContext(), resource);
        view.setCompoundDrawablesWithIntrinsicBounds(id, 0, 0, 0);
    }

    @ReactProp(name = "inlineImagePadding")
    public void setInlineImagePadding(ReactEditText view, int padding) {
        view.setCompoundDrawablePadding(padding);
    }

    @ReactProp(name = "editable", defaultBoolean = true)
    public void setEditable(ReactEditText view, boolean editable) {
        view.setEnabled(editable);
    }

    @ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = 1)
    public void setNumLines(ReactEditText view, int numLines) {
        view.setLines(numLines);
    }

    @ReactProp(name = "maxLength")
    public void setMaxLength(ReactEditText view, @Nullable Integer maxLength) {
        InputFilter[] currentFilters = view.getFilters();
        InputFilter[] newFilters = EMPTY_FILTERS;
        if (maxLength == null) {
            if (currentFilters.length > 0) {
                LinkedList<InputFilter> list = new LinkedList<>();
                for (int i = 0; i < currentFilters.length; i++) {
                    if (!(currentFilters[i] instanceof InputFilter.LengthFilter)) {
                        list.add(currentFilters[i]);
                    }
                }
                if (!list.isEmpty()) {
                    newFilters = (InputFilter[]) list.toArray(new InputFilter[list.size()]);
                }
            }
        } else {
            if (currentFilters.length > 0) {
                newFilters = currentFilters;
                boolean replaced = false;
                for (int i = 0; i < currentFilters.length; i++) {
                    if (currentFilters[i] instanceof InputFilter.LengthFilter) {
                        currentFilters[i] = new InputFilter.LengthFilter(maxLength);
                        replaced = true;
                    }
                }
                if (!replaced) {
                    newFilters = new InputFilter[currentFilters.length + 1];
                    System.arraycopy(currentFilters, 0, newFilters, 0, currentFilters.length);
                    currentFilters[currentFilters.length] = new InputFilter.LengthFilter(maxLength);
                }
            } else {
                newFilters = new InputFilter[1];
                newFilters[0] = new InputFilter.LengthFilter(maxLength);
            }
        }
        view.setFilters(newFilters);
    }

    @ReactProp(name = "autoCorrect")
    public void setAutoCorrect(ReactEditText view, @Nullable Boolean autoCorrect) {
        // clear auto correct flags, set SUGGESTIONS or NO_SUGGESTIONS depending on value
        updateStagedInputTypeFlag(view, InputType.TYPE_TEXT_FLAG_AUTO_CORRECT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS, autoCorrect != null ? (autoCorrect.booleanValue() ? InputType.TYPE_TEXT_FLAG_AUTO_CORRECT : InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) : 0);
    }

    @ReactProp(name = "multiline", defaultBoolean = false)
    public void setMultiline(ReactEditText view, boolean multiline) {
        updateStagedInputTypeFlag(view, multiline ? 0 : InputType.TYPE_TEXT_FLAG_MULTI_LINE, multiline ? InputType.TYPE_TEXT_FLAG_MULTI_LINE : 0);
    }

    @ReactProp(name = "secureTextEntry", defaultBoolean = false)
    public void setSecureTextEntry(ReactEditText view, boolean preplacedword) {
        updateStagedInputTypeFlag(view, preplacedword ? 0 : InputType.TYPE_NUMBER_VARIATION_PreplacedWORD | InputType.TYPE_TEXT_VARIATION_PreplacedWORD, preplacedword ? InputType.TYPE_TEXT_VARIATION_PreplacedWORD : 0);
        checkPreplacedwordType(view);
    }

    @ReactProp(name = "autoCapitalize")
    public void setAutoCapitalize(ReactEditText view, int autoCapitalize) {
        updateStagedInputTypeFlag(view, InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_CAP_WORDS | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS, autoCapitalize);
    }

    @ReactProp(name = "keyboardType")
    public void setKeyboardType(ReactEditText view, @Nullable String keyboardType) {
        int flagsToSet = InputType.TYPE_CLreplaced_TEXT;
        if (KEYBOARD_TYPE_NUMERIC.equalsIgnoreCase(keyboardType)) {
            flagsToSet = INPUT_TYPE_KEYBOARD_NUMBERED;
        } else if (KEYBOARD_TYPE_NUMBER_PAD.equalsIgnoreCase(keyboardType)) {
            flagsToSet = INPUT_TYPE_KEYBOARD_NUMBER_PAD;
        } else if (KEYBOARD_TYPE_DECIMAL_PAD.equalsIgnoreCase(keyboardType)) {
            flagsToSet = INPUT_TYPE_KEYBOARD_DECIMAL_PAD;
        } else if (KEYBOARD_TYPE_EMAIL_ADDRESS.equalsIgnoreCase(keyboardType)) {
            flagsToSet = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLreplaced_TEXT;
        } else if (KEYBOARD_TYPE_PHONE_PAD.equalsIgnoreCase(keyboardType)) {
            flagsToSet = InputType.TYPE_CLreplaced_PHONE;
        } else if (KEYBOARD_TYPE_VISIBLE_PreplacedWORD.equalsIgnoreCase(keyboardType)) {
            // This will supercede secureTextEntry={false}. If it doesn't, due to the way
            // the flags work out, the underlying field will end up a URI-type field.
            flagsToSet = InputType.TYPE_TEXT_VARIATION_VISIBLE_PreplacedWORD;
        }
        updateStagedInputTypeFlag(view, KEYBOARD_TYPE_FLAGS, flagsToSet);
        checkPreplacedwordType(view);
    }

    @ReactProp(name = "returnKeyType")
    public void setReturnKeyType(ReactEditText view, String returnKeyType) {
        view.setReturnKeyType(returnKeyType);
    }

    @ReactProp(name = "disableFullscreenUI", defaultBoolean = false)
    public void setDisableFullscreenUI(ReactEditText view, boolean disableFullscreenUI) {
        view.setDisableFullscreenUI(disableFullscreenUI);
    }

    private static final int IME_ACTION_ID = 0x670;

    @ReactProp(name = "returnKeyLabel")
    public void setReturnKeyLabel(ReactEditText view, String returnKeyLabel) {
        view.setImeActionLabel(returnKeyLabel, IME_ACTION_ID);
    }

    @ReactPropGroup(names = { ViewProps.BORDER_RADIUS, ViewProps.BORDER_TOP_LEFT_RADIUS, ViewProps.BORDER_TOP_RIGHT_RADIUS, ViewProps.BORDER_BOTTOM_RIGHT_RADIUS, ViewProps.BORDER_BOTTOM_LEFT_RADIUS }, defaultFloat = YogaConstants.UNDEFINED)
    public void setBorderRadius(ReactEditText view, int index, float borderRadius) {
        if (!YogaConstants.isUndefined(borderRadius)) {
            borderRadius = PixelUtil.toPixelFromDIP(borderRadius);
        }
        if (index == 0) {
            view.setBorderRadius(borderRadius);
        } else {
            view.setBorderRadius(borderRadius, index - 1);
        }
    }

    @ReactProp(name = "borderStyle")
    public void setBorderStyle(ReactEditText view, @Nullable String borderStyle) {
        view.setBorderStyle(borderStyle);
    }

    @ReactPropGroup(names = { ViewProps.BORDER_WIDTH, ViewProps.BORDER_LEFT_WIDTH, ViewProps.BORDER_RIGHT_WIDTH, ViewProps.BORDER_TOP_WIDTH, ViewProps.BORDER_BOTTOM_WIDTH }, defaultFloat = YogaConstants.UNDEFINED)
    public void setBorderWidth(ReactEditText view, int index, float width) {
        if (!YogaConstants.isUndefined(width)) {
            width = PixelUtil.toPixelFromDIP(width);
        }
        view.setBorderWidth(SPACING_TYPES[index], width);
    }

    @ReactPropGroup(names = { "borderColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor" }, customType = "Color")
    public void setBorderColor(ReactEditText view, int index, Integer color) {
        float rgbComponent = color == null ? YogaConstants.UNDEFINED : (float) ((int) color & 0x00FFFFFF);
        float alphaComponent = color == null ? YogaConstants.UNDEFINED : (float) ((int) color >>> 24);
        view.setBorderColor(SPACING_TYPES[index], rgbComponent, alphaComponent);
    }

    @Override
    protected void onAfterUpdateTransaction(ReactEditText view) {
        super.onAfterUpdateTransaction(view);
        view.commitStagedInputType();
    }

    // Sets the correct preplacedword type, since numeric and text preplacedwords have different types
    private static void checkPreplacedwordType(ReactEditText view) {
        if ((view.getStagedInputType() & INPUT_TYPE_KEYBOARD_NUMBERED) != 0 && (view.getStagedInputType() & InputType.TYPE_TEXT_VARIATION_PreplacedWORD) != 0) {
            // Text input type is numbered preplacedword, remove text preplacedword variation, add numeric one
            updateStagedInputTypeFlag(view, InputType.TYPE_TEXT_VARIATION_PreplacedWORD, InputType.TYPE_NUMBER_VARIATION_PreplacedWORD);
        }
    }

    /**
     * This code was taken from the method parseNumericFontWeight of the clreplaced ReactTextShadowNode
     * TODO: Factor into a common place they can both use
     *
     * Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
     * return the weight.
     */
    private static int parseNumericFontWeight(String fontWeightString) {
        // This should be much faster than using regex to verify input and Integer.parseInt
        return fontWeightString.length() == 3 && fontWeightString.endsWith("00") && fontWeightString.charAt(0) <= '9' && fontWeightString.charAt(0) >= '1' ? 100 * (fontWeightString.charAt(0) - '0') : -1;
    }

    private static void updateStagedInputTypeFlag(ReactEditText view, int flagsToUnset, int flagsToSet) {
        view.setStagedInputType((view.getStagedInputType() & ~flagsToUnset) | flagsToSet);
    }

    private clreplaced ReactTextInputTexreplacedcher implements Texreplacedcher {

        private EventDispatcher mEventDispatcher;

        private ReactEditText mEditText;

        private String mPreviousText;

        public ReactTextInputTexreplacedcher(final ReactContext reactContext, final ReactEditText editText) {
            mEventDispatcher = reactContext.getNativeModule(UIManagerModule.clreplaced).getEventDispatcher();
            mEditText = editText;
            mPreviousText = null;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // Incoming charSequence gets mutated before onTextChanged() is invoked
            mPreviousText = s.toString();
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // Rearranging the text (i.e. changing between singleline and multiline attributes) can
            // also trigger onTextChanged, call the event in JS only when the text actually changed
            if (count == 0 && before == 0) {
                return;
            }
            replacedertions.replacedertNotNull(mPreviousText);
            String newText = s.toString().substring(start, start + count);
            String oldText = mPreviousText.substring(start, start + before);
            // Don't send same text changes
            if (count == before && newText.equals(oldText)) {
                return;
            }
            // The event that contains the event counter and updates it must be sent first.
            // TODO: t7936714 merge these events
            mEventDispatcher.dispatchEvent(new ReactTextChangedEvent(mEditText.getId(), s.toString(), mEditText.incrementAndGetEventCounter()));
            mEventDispatcher.dispatchEvent(new ReactTextInputEvent(mEditText.getId(), newText, oldText, start, start + before));
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    }

    @Override
    protected void addEventEmitters(final ThemedReactContext reactContext, final ReactEditText editText) {
        editText.addTextChangedListener(new ReactTextInputTexreplacedcher(reactContext, editText));
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {

            public void onFocusChange(View v, boolean hasFocus) {
                EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.clreplaced).getEventDispatcher();
                if (hasFocus) {
                    eventDispatcher.dispatchEvent(new ReactTextInputFocusEvent(editText.getId()));
                } else {
                    eventDispatcher.dispatchEvent(new ReactTextInputBlurEvent(editText.getId()));
                    eventDispatcher.dispatchEvent(new ReactTextInputEndEditingEvent(editText.getId(), editText.getText().toString()));
                }
            }
        });
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent keyEvent) {
                // Any 'Enter' action will do
                if ((actionId & EditorInfo.IME_MASK_ACTION) > 0 || actionId == EditorInfo.IME_NULL) {
                    boolean blurOnSubmit = editText.getBlurOnSubmit();
                    boolean isMultiline = ((editText.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0);
                    // Motivation:
                    // * blurOnSubmit && isMultiline => Clear focus; prevent default behaviour (return true);
                    // * blurOnSubmit && !isMultiline => Clear focus; prevent default behaviour (return true);
                    // * !blurOnSubmit && isMultiline => Perform default behaviour (return false);
                    // * !blurOnSubmit && !isMultiline => Prevent default behaviour (return true).
                    // Additionally we always generate a `submit` event.
                    EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.clreplaced).getEventDispatcher();
                    eventDispatcher.dispatchEvent(new ReactTextInputSubmitEditingEvent(editText.getId(), editText.getText().toString()));
                    if (blurOnSubmit) {
                        editText.clearFocus();
                    }
                    // Prevent default behavior except when we want it to insert a newline.
                    return blurOnSubmit || !isMultiline;
                }
                return true;
            }
        });
    }

    private clreplaced ReactContentSizeWatcher implements ContentSizeWatcher {

        private ReactEditText mEditText;

        private EventDispatcher mEventDispatcher;

        private int mPreviousContentWidth = 0;

        private int mPreviousContentHeight = 0;

        public ReactContentSizeWatcher(ReactEditText editText) {
            mEditText = editText;
            ReactContext reactContext = (ReactContext) editText.getContext();
            mEventDispatcher = reactContext.getNativeModule(UIManagerModule.clreplaced).getEventDispatcher();
        }

        @Override
        public void onLayout() {
            int contentWidth = mEditText.getWidth();
            int contentHeight = mEditText.getHeight();
            // Use instead size of text content within EditText when available
            if (mEditText.getLayout() != null) {
                contentWidth = mEditText.getCompoundPaddingLeft() + mEditText.getLayout().getWidth() + mEditText.getCompoundPaddingRight();
                contentHeight = mEditText.getCompoundPaddingTop() + mEditText.getLayout().getHeight() + mEditText.getCompoundPaddingBottom();
            }
            if (contentWidth != mPreviousContentWidth || contentHeight != mPreviousContentHeight) {
                mPreviousContentHeight = contentHeight;
                mPreviousContentWidth = contentWidth;
                mEventDispatcher.dispatchEvent(new ReactContentSizeChangedEvent(mEditText.getId(), PixelUtil.toDIPFromPixel(contentWidth), PixelUtil.toDIPFromPixel(contentHeight)));
            }
        }
    }

    private clreplaced ReactSelectionWatcher implements SelectionWatcher {

        private ReactEditText mReactEditText;

        private EventDispatcher mEventDispatcher;

        private int mPreviousSelectionStart;

        private int mPreviousSelectionEnd;

        public ReactSelectionWatcher(ReactEditText editText) {
            mReactEditText = editText;
            ReactContext reactContext = (ReactContext) editText.getContext();
            mEventDispatcher = reactContext.getNativeModule(UIManagerModule.clreplaced).getEventDispatcher();
        }

        @Override
        public void onSelectionChanged(int start, int end) {
            // Android will call us back for both the SELECTION_START span and SELECTION_END span in text
            // To prevent double calling back into js we cache the result of the previous call and only
            // forward it on if we have new values
            if (mPreviousSelectionStart != start || mPreviousSelectionEnd != end) {
                mEventDispatcher.dispatchEvent(new ReactTextInputSelectionEvent(mReactEditText.getId(), start, end));
                mPreviousSelectionStart = start;
                mPreviousSelectionEnd = end;
            }
        }
    }

    private clreplaced ReactScrollWatcher implements ScrollWatcher {

        private ReactEditText mReactEditText;

        private EventDispatcher mEventDispatcher;

        private int mPreviousHoriz;

        private int mPreviousVert;

        public ReactScrollWatcher(ReactEditText editText) {
            mReactEditText = editText;
            ReactContext reactContext = (ReactContext) editText.getContext();
            mEventDispatcher = reactContext.getNativeModule(UIManagerModule.clreplaced).getEventDispatcher();
        }

        @Override
        public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
            if (mPreviousHoriz != horiz || mPreviousVert != vert) {
                ScrollEvent event = ScrollEvent.obtain(mReactEditText.getId(), ScrollEventType.SCROLL, horiz, vert, // can't get x velocity
                0f, // can't get y velocity
                0f, // can't get content width
                0, // can't get content height
                0, mReactEditText.getWidth(), mReactEditText.getHeight());
                mEventDispatcher.dispatchEvent(event);
                mPreviousHoriz = horiz;
                mPreviousVert = vert;
            }
        }
    }

    @Override
    @Nullable
    public Map getExportedViewConstants() {
        return MapBuilder.of("AutoCapitalizationType", MapBuilder.of("none", 0, "characters", InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS, "words", InputType.TYPE_TEXT_FLAG_CAP_WORDS, "sentences", InputType.TYPE_TEXT_FLAG_CAP_SENTENCES));
    }
}

19 Source : TextInputSpec.java
with Apache License 2.0
from facebook

/**
 * LengthFilter and AllCaps do not implement isEqual. Correct for the deficiency.
 */
static boolean equalInputFilters(List<InputFilter> a, List<InputFilter> b) {
    if (a == null && b == null) {
        return true;
    }
    if (a == null || b == null) {
        return false;
    }
    if (a.size() != b.size()) {
        return false;
    }
    for (int i = 0; i < a.size(); i++) {
        InputFilter fa = a.get(i);
        InputFilter fb = b.get(i);
        if (fa instanceof InputFilter.AllCaps && fb instanceof InputFilter.AllCaps) {
            // equal, AllCaps has no configuration
            continue;
        }
        if (SDK_INT >= LOLLIPOP) {
            // getMax added in lollipop
            if (fa instanceof InputFilter.LengthFilter && fb instanceof InputFilter.LengthFilter) {
                if (((InputFilter.LengthFilter) fa).getMax() != ((InputFilter.LengthFilter) fb).getMax()) {
                    return false;
                }
                // equal, same max
                continue;
            }
        }
        // Best we can do in this case is call equals().
        if (!ObjectsCompat.equals(fa, fb)) {
            return false;
        }
    }
    return true;
}

19 Source : BackupPreferences.java
with GNU General Public License v3.0
from eszdman

public clreplaced BackupPreferences extends EditTextPreference {

    public BackupPreferences(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        setPersistent(false);
        setSummary(FileManager.sPHOTON_DIR.toString());
        // temporary
        setDialogMessage("(Per lens settings are not backed up at the moment)");
        setOnBindEditTextListener(editText -> {
            editText.setText(getContext().getString(R.string.backup_file_name, new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date())));
            editText.setFilters(new InputFilter[] { textInputFilter });
        });
    }

    private final InputFilter textInputFilter = (source, start, end, dest, dstart, dend) -> {
        if (source instanceof SpannableStringBuilder) {
            SpannableStringBuilder sourcereplacedpannableBuilder = (SpannableStringBuilder) source;
            for (int i = end - 1; i >= start; i--) {
                char currentChar = source.charAt(i);
                if (!isAcceptedCharacter(currentChar)) {
                    Toast.makeText(getContext(), "Invalid '" + currentChar + "'", Toast.LENGTH_SHORT).show();
                    sourcereplacedpannableBuilder.delete(i, i + 1);
                }
            }
            return source;
        } else {
            StringBuilder filteredStringBuilder = new StringBuilder();
            for (int i = start; i < end; i++) {
                char currentChar = source.charAt(i);
                if (isAcceptedCharacter(currentChar)) {
                    filteredStringBuilder.append(currentChar);
                } else {
                    Toast.makeText(getContext(), "Invalid '" + currentChar + "'", Toast.LENGTH_SHORT).show();
                }
            }
            return filteredStringBuilder.toString();
        }
    };

    boolean isAcceptedCharacter(char character) {
        return Character.isLetterOrDigit(character) || character == '_';
    }
}

19 Source : UtilTools.java
with Apache License 2.0
from Equalzys

/**
 * 禁止EditText输入特殊字符和空格
 *
 * @param editText
 */
public static void setEditTextInhibitInputSpeChat(EditText editText) {
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            String speChat = "[`~!@#$%^&*()+=_-|{}':;',\\[\\]" + ".<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
            Pattern pattern = Pattern.compile(speChat);
            Matcher matcher = pattern.matcher(source.toString());
            if (matcher.find() || source.equals(" ")) {
                return "";
            } else {
                return null;
            }
        }
    };
    editText.setFilters(new InputFilter[] { filter });
}

19 Source : UtilTools.java
with Apache License 2.0
from Equalzys

/**
 * 禁止EditText输入特殊字符和空格 和最大长度
 *
 * @param editText
 */
public static void setEditTextInhibitInputSpeChat(EditText editText, final int maxLength) {
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            String speChat = "[`~!@#$%^&*()+=_-|{}':;',\\[\\]" + ".<>/?~!@#¥……&*()——+|{}【】‘;:”“’。,、?]";
            Pattern pattern = Pattern.compile(speChat);
            Matcher matcher = pattern.matcher(source.toString());
            if (matcher.find() || source.equals(" ") || dend > maxLength || end > 3) {
                return "";
            } else {
                return null;
            }
        }
    };
    editText.setFilters(new InputFilter[] { filter });
}

19 Source : UtilTools.java
with Apache License 2.0
from Equalzys

/**
 * 禁止EditText输入空格
 *
 * @param editText
 */
public static void setEditTextInhibitInputSpace(EditText editText) {
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.equals(" ")) {
                return "";
            } else {
                return null;
            }
        }
    };
    editText.setFilters(new InputFilter[] { filter });
}

19 Source : UtilTools.java
with Apache License 2.0
from Equalzys

// /**
// * 通过Uri跳转到百度地图导航
// */
// public static void startNative_Baidu(Activity activity, LatLng pt1, LatLng pt2) {
// try {
// double dis = DistanceUtil.getDistance(new LatLng(pt1.lareplacedude, pt1.longitude), new
// LatLng(pt2.lareplacedude, pt2.longitude));
// if (dis <= 100) {
// Toast.makeText(activity, "起点、途经点、终点距离太近", Toast.LENGTH_SHORT).show();
// return;
// }
// String start_latlng = pt1.lareplacedude + "," + pt1.longitude;
// String end_latlng = pt2.lareplacedude + "," + pt2.longitude;
// Intent intent = Intent.getIntent("intent://map/direction?origin=latlng:" +
// start_latlng + "|name:" + "Start" + "&destination=latlng:" + end_latlng + "|name:" + "End" +
// "&mode=riding&src=这里随便写#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end");
// activity.startActivity(intent);
// } catch (Exception e) {
// e.printStackTrace();
// Toast.makeText(activity, "地址解析错误", Toast.LENGTH_SHORT).show();
// }
// }
/**
 * 禁止EditText输入空格和限制最大位数
 *
 * @param editText
 */
public static void setEditTextInhibitInputSpace(EditText editText, final int maxLength) {
    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.equals(" ") || dend > maxLength || end > 3) {
                return "";
            } else {
                return null;
            }
        }
    };
    editText.setFilters(new InputFilter[] { filter });
}

19 Source : NumberAutoFormatWatcher.java
with Apache License 2.0
from DjamshidDjurayev

clreplaced NumberAutoFormareplacedcher implements Texreplacedcher {

    // by default 2
    private int decimalFractions = 2;

    // by default 9
    private int integerFractions = 9;

    private boolean isFormatting;

    private InputFilter filter;

    public int getIntegerFractions() {
        return integerFractions;
    }

    public void setIntegerFractions(int integerFractions) {
        this.integerFractions = integerFractions;
    }

    private int getDecimalFractions() {
        return decimalFractions;
    }

    public void setDecimalFractions(int decimalFractions) {
        this.decimalFractions = decimalFractions;
    }

    private InputFilter getFilter() {
        return filter;
    }

    public void setFilter(InputFilter filter) {
        this.filter = filter;
    }

    NumberAutoFormareplacedcher() {
        isFormatting = false;
    }

    public synchronized void afterTextChanged(Editable s) {
        if (isFormatting) {
            return;
        }
        if (s.length() > 0) {
            isFormatting = true;
            inputFormat(s);
            isFormatting = false;
        }
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

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

    private void inputFormat(Editable input) {
        input.setFilters(new InputFilter[] { filter });
        if (input.toString().startsWith(".") && input.toString().length() == 1) {
            input.clear();
            input.append("0.");
            return;
        }
        if (input.toString().contains(".")) {
            String[] splicedText = input.toString().split("\\.");
            if (splicedText.length == 0) {
                return;
            }
            String strippedIntegerText = InputUtils.stripSpaces(splicedText[0]);
            // set limit for integer input with decimals
            if (strippedIntegerText.length() > integerFractions) {
                strippedIntegerText = strippedIntegerText.substring(0, integerFractions);
                strippedIntegerText = InputUtils.formatWithoutDecimal(strippedIntegerText);
                try {
                    input.replace(0, splicedText[0].length(), strippedIntegerText);
                } catch (NumberFormatException nfe) {
                    input.clear();
                }
                // when pasting value like 1 000 000 000.999 we should check for digits limitations
                // both integers and decimals
                if (!(splicedText.length > 1 && splicedText[1].length() > decimalFractions)) {
                    return;
                }
            }
            String strippedDecimalText = "";
            if (splicedText.length > 1) {
                strippedDecimalText = InputUtils.stripSpaces(splicedText[1]);
            }
            // set limit for decimal input
            if (strippedDecimalText.length() > decimalFractions) {
                int dotPosition = InputUtils.findDotPosition(input.toString());
                strippedDecimalText = strippedDecimalText.substring(0, decimalFractions);
                try {
                    input.replace(dotPosition + 1, input.length(), strippedDecimalText);
                } catch (NumberFormatException nfe) {
                    input.clear();
                }
                return;
            } else {
                int newDotPosition = InputUtils.findDotPosition(input.toString());
                input.replace(newDotPosition + 1, input.length(), strippedDecimalText);
            }
            String digits = InputUtils.stripSpaces(splicedText[0]);
            int dotPosition = InputUtils.findDotPosition(input.toString());
            try {
                String formatted = InputUtils.formatWithoutDecimal(digits);
                input.replace(0, dotPosition, formatted);
            } catch (NumberFormatException nfe) {
                input.clear();
            }
        } else {
            String digits = InputUtils.stripSpaces(input.toString());
            // set limit for integer input without decimals
            if (digits.length() > integerFractions) {
                digits = digits.substring(0, integerFractions);
                digits = InputUtils.formatWithoutDecimal(digits);
                try {
                    input.replace(0, input.length(), digits);
                } catch (NumberFormatException nfe) {
                    input.clear();
                }
                return;
            }
            try {
                String formatted = InputUtils.formatWithoutDecimal(digits);
                input.replace(0, input.length(), formatted);
            } catch (NumberFormatException nfe) {
                input.clear();
            }
        }
    }
}

19 Source : NumberAutoFormatWatcher.java
with Apache License 2.0
from DjamshidDjurayev

public void setFilter(InputFilter filter) {
    this.filter = filter;
}

19 Source : MainActivity.java
with Apache License 2.0
from DjamshidDjurayev

public clreplaced MainActivity extends AppCompatActivity {

    protected EditText input;

    protected NumberAutoFormareplacedcher numberAutoFormareplacedcher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        input = findViewById(R.id.input);
        numberAutoFormareplacedcher = new NumberAutoFormareplacedcher();
        numberAutoFormareplacedcher.setFilter(filter);
        numberAutoFormareplacedcher.setDecimalFractions(2);
        numberAutoFormareplacedcher.setIntegerFractions(9);
        input.setFilters(new InputFilter[] { filter });
        input.addTextChangedListener(numberAutoFormareplacedcher);
    }

    InputFilter filter = new InputFilter() {

        @Override
        public CharSequence filter(CharSequence source, int i, int i1, Spanned spanned, int i2, int i3) {
            String fullString = input.getText().toString() + source.toString();
            int dotAmount = InputUtils.getSignOccurance(fullString, '.');
            // preventing multiple dots
            if (dotAmount > 1) {
                return "";
            }
            return source;
        }
    };
}

19 Source : EmojiTextViewHelperTest.java
with Apache License 2.0
from androidx

private EmojiInputFilter findEmojiInputFilter(final InputFilter[] filters) {
    for (int i = 0; i < filters.length; i++) {
        if (filters[i] instanceof EmojiInputFilter) {
            return (EmojiInputFilter) filters[i];
        }
    }
    return null;
}

18 Source : EmojiEditText.java
with GNU General Public License v3.0
from XecureIT

private InputFilter[] appendEmojiFilter(@Nullable InputFilter[] originalFilters) {
    InputFilter[] result;
    if (originalFilters != null) {
        result = new InputFilter[originalFilters.length + 1];
        System.arraycopy(originalFilters, 0, result, 1, originalFilters.length);
    } else {
        result = new InputFilter[1];
    }
    result[0] = new EmojiFilter(this);
    return result;
}

18 Source : PassWordInputLayout.java
with MIT License
from why168

private void addSpaceHandler(EditText et) {
    final InputFilter filter = (source, start, end, dest, dstart, dend) -> {
        for (int i = start; i < end; i++) {
            if (Character.isWhitespace(source.charAt(i))) {
                tryAddSuggestion();
                return "";
            }
        }
        return null;
    };
    et.setFilters(new InputFilter[] { filter });
}

18 Source : MyEditable.java
with GNU General Public License v3.0
from wangchen11

@Override
public void setFilters(InputFilter[] filters) {
}

18 Source : ComposeEditText.java
with GNU Affero General Public License v3.0
from threema-ch

/**
 * Add our MentionFilter as the first item to the array of existing InputFilters
 * @param originalFilters
 * @return Array of filters
 */
private InputFilter[] appendMentionFilter(@Nullable InputFilter[] originalFilters) {
    InputFilter[] result;
    if (originalFilters != null) {
        result = new InputFilter[originalFilters.length + 1];
        System.arraycopy(originalFilters, 0, result, 1, originalFilters.length);
    } else {
        result = new InputFilter[1];
    }
    result[0] = new MentionFilter(this.context);
    return result;
}

18 Source : EmojiEditText.java
with GNU Affero General Public License v3.0
from threema-ch

/**
 * Add our EmojiFilter as the first item to the array of existing InputFilters
 * @param originalFilters
 * @return Array of filters
 */
private InputFilter[] appendEmojiFilter(@Nullable InputFilter[] originalFilters) {
    InputFilter[] result;
    if (originalFilters != null) {
        result = new InputFilter[originalFilters.length + 1];
        System.arraycopy(originalFilters, 0, result, 1, originalFilters.length);
    } else {
        result = new InputFilter[1];
    }
    result[0] = new EmojiFilter(this);
    return result;
}

18 Source : MongolTextStorage.java
with MIT License
from suragch

@Override
public void setFilters(InputFilter[] filters) {
    if (!(mUnicodeText instanceof SpannableStringBuilder)) {
        return;
    }
    // TODO: this is untested!
    int oldLength = mUnicodeText.length();
    ((SpannableStringBuilder) mUnicodeText).setFilters(filters);
    ((SpannableStringBuilder) mGlyphText).setFilters(filters);
    if (mChangelistener != null)
        mChangelistener.onTextChanged(mUnicodeText, 0, oldLength, mUnicodeText.length());
}

18 Source : ChatActivity.java
with MIT License
from stytooldex

public void setProhibitEmoji(EditText et) {
    InputFilter[] filters = { getInputFilterProhibitEmoji(), getInputFilterProhibitSP() };
    et.setFilters(filters);
}

18 Source : EditMessage.java
with GNU General Public License v3.0
from snikket-im

public clreplaced EditMessage extends EmojiWrapperEditText {

    private static final InputFilter SPAN_FILTER = (source, start, end, dest, dstart, dend) -> source instanceof Spanned ? source.toString() : source;

    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    protected Handler mTypingHandler = new Handler();

    protected KeyboardListener keyboardListener;

    private OnCommitContentListener mCommitContentListener = null;

    private String[] mimeTypes = null;

    private boolean isUserTyping = false;

    private final Runnable mTypingTimeout = new Runnable() {

        @Override
        public void run() {
            if (isUserTyping && keyboardListener != null) {
                keyboardListener.onTypingStopped();
                isUserTyping = false;
            }
        }
    };

    private boolean lastInputWasTab = false;

    public EditMessage(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditMessage(Context context) {
        super(context);
    }

    @Override
    public boolean onKeyDown(final int keyCode, final KeyEvent e) {
        final boolean isCtrlPressed = e.isCtrlPressed();
        if (keyCode == KeyEvent.KEYCODE_ENTER && !e.isShiftPressed()) {
            lastInputWasTab = false;
            if (keyboardListener != null && keyboardListener.onEnterPressed(isCtrlPressed)) {
                return true;
            }
        } else if (keyCode == KeyEvent.KEYCODE_TAB && !e.isAltPressed() && !isCtrlPressed) {
            if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) {
                lastInputWasTab = true;
                return true;
            }
        } else {
            lastInputWasTab = false;
        }
        return super.onKeyDown(keyCode, e);
    }

    @Override
    public int getAutofillType() {
        return AUTOFILL_TYPE_NONE;
    }

    @Override
    public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        lastInputWasTab = false;
        if (this.mTypingHandler != null && this.keyboardListener != null) {
            executor.execute(() -> triggerKeyboardEvents(text.length()));
        }
    }

    private void triggerKeyboardEvents(final int length) {
        final KeyboardListener listener = this.keyboardListener;
        if (listener == null) {
            return;
        }
        this.mTypingHandler.removeCallbacks(mTypingTimeout);
        this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000);
        if (!isUserTyping && length > 0) {
            this.isUserTyping = true;
            listener.onTypingStarted();
        } else if (length == 0) {
            this.isUserTyping = false;
            listener.onTextDeleted();
        }
        listener.onTextChanged();
    }

    public void setKeyboardListener(KeyboardListener listener) {
        this.keyboardListener = listener;
        if (listener != null) {
            this.isUserTyping = false;
        }
    }

    @Override
    public boolean onTextContextMenuItem(int id) {
        if (id == android.R.id.paste) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
            } else {
                Editable editable = getEditableText();
                InputFilter[] filters = editable.getFilters();
                InputFilter[] tempFilters = new InputFilter[filters != null ? filters.length + 1 : 1];
                if (filters != null) {
                    System.arraycopy(filters, 0, tempFilters, 1, filters.length);
                }
                tempFilters[0] = SPAN_FILTER;
                editable.setFilters(tempFilters);
                try {
                    return super.onTextContextMenuItem(id);
                } finally {
                    editable.setFilters(filters);
                }
            }
        } else {
            return super.onTextContextMenuItem(id);
        }
    }

    public void setRichContentListener(String[] mimeTypes, OnCommitContentListener listener) {
        this.mimeTypes = mimeTypes;
        this.mCommitContentListener = listener;
    }

    public void insertAsQuote(String text) {
        text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", "");
        Editable editable = getEditableText();
        int position = getSelectionEnd();
        if (position == -1)
            position = editable.length();
        if (position > 0 && editable.charAt(position - 1) != '\n') {
            editable.insert(position++, "\n");
        }
        editable.insert(position, text);
        position += text.length();
        editable.insert(position++, "\n");
        if (position < editable.length() && editable.charAt(position) != '\n') {
            editable.insert(position, "\n");
        }
        setSelection(position);
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
        final InputConnection ic = super.onCreateInputConnection(editorInfo);
        if (mimeTypes != null && mCommitContentListener != null && ic != null) {
            EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes);
            return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes));
        } else {
            return ic;
        }
    }

    public void refreshIme() {
        SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(getContext());
        final boolean usingEnterKey = p.getBoolean("display_enter_key", getResources().getBoolean(R.bool.display_enter_key));
        final boolean enterIsSend = p.getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send));
        if (usingEnterKey && enterIsSend) {
            setInputType(getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE));
            setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
        } else if (usingEnterKey) {
            setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
            setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
        } else {
            setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
            setInputType(getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
        }
    }

    public interface OnCommitContentListener {

        boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] mimeTypes);
    }

    public interface KeyboardListener {

        boolean onEnterPressed(boolean isCtrlPressed);

        void onTypingStarted();

        void onTypingStopped();

        void onTextDeleted();

        void onTextChanged();

        boolean onTabPressed(boolean repeated);
    }
}

18 Source : LatinEditText.java
with Apache License 2.0
from shenghuntianlang

private void init(Context context) {
    InputFilter filter = new InputFilter() {

        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; i++) {
                if (!(ACCEPT_CHAR.matcher(source.charAt(i) + "").find())) {
                    return "";
                }
            }
            return null;
        }
    };
    setFilters(new InputFilter[] { filter });
    setInputType(InputType.TYPE_CLreplaced_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}

18 Source : ItemPicker.java
with Apache License 2.0
from saki4510t

/**
 * A view for selecting a number or string-array
 */
public final clreplaced ItemPicker extends LinearLayout {

    /**
     * The callback interface used to indicate the item value has been adjusted.
     */
    public interface OnChangedListener {

        /**
         * @param picker The NumberPicker replacedociated with this listener.
         * @param oldVal The previous value.
         * @param newVal The new value.
         */
        void onChanged(ItemPicker picker, int oldVal, int newVal);
    }

    /**
     * Interface used to format the item into a string for presentation
     */
    public interface Formatter {

        String toString(int value);
    }

    private final Handler mHandler = new Handler();

    private final Runnable mRunnable = new Runnable() {

        @Override
        public void run() {
            if (mIncrement) {
                changeCurrent(mCurrentValue + 1);
                mHandler.postDelayed(this, mSpeed);
            } else if (mDecrement) {
                changeCurrent(mCurrentValue - 1);
                mHandler.postDelayed(this, mSpeed);
            }
        }
    };

    private final EditText mText;

    private final InputFilter mNumberInputFilter;

    private String[] mDisplayedValues;

    /**
     * Lower value of the range of numbers allowed for the ItemPicker
     */
    private int mMinValue;

    /**
     * Upper value of the range of numbers allowed for the ItemPicker
     */
    private int mMaxValue;

    /**
     * Current value of this ItemPicker
     */
    private int mCurrentValue;

    /**
     * Previous value of this ItemPicker.
     */
    private int mPrevValue;

    private OnChangedListener mListener;

    private Formatter mFormatter;

    private long mSpeed = 300;

    private boolean mIncrement;

    private boolean mDecrement;

    /**
     * Create a new item picker
     * @param context the application environment
     */
    public ItemPicker(final Context context) {
        this(context, null);
    }

    public ItemPicker(final Context context, final AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * Create a new item picker
     * @param context the application environment
     * @param attrs a collection of attributes
     * @param defStyle
     */
    public ItemPicker(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs);
        setOrientation(HORIZONTAL);
        setGravity(Gravity.CENTER_VERTICAL);
        final LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.item_picker, this, true);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ItemPicker, defStyle, 0);
        final int minValue = a.getInt(R.styleable.ItemPicker_ItemPickerMinItemValue, -1);
        final int maxValue = a.getInt(R.styleable.ItemPicker_ItemPickerMaxItemValue, -1);
        final int displayedValueId = a.getResourceId(R.styleable.ItemPicker_ItemPickerDisplayedValue, -1);
        final String[] displayedValue = (displayedValueId > -1) ? getResources().getStringArray(displayedValueId) : null;
        final int incrementBackground = a.getResourceId(R.styleable.ItemPicker_ItemPickerIncrementBackground, -1);
        final int decrementBackground = a.getResourceId(R.styleable.ItemPicker_ItemPickerDecrementBackground, -1);
        final int incrementSrc = a.getResourceId(R.styleable.ItemPicker_ItemPickerIncrementSrc, -1);
        final int decrementSrc = a.getResourceId(R.styleable.ItemPicker_ItemPickerDecrementSrc, -1);
        final int editTextBackground = a.getResourceId(R.styleable.ItemPicker_ItemPickerEditTextBackground, -1);
        final int currentValue = a.getInt(R.styleable.ItemPicker_ItemPickerCurrenreplacedemValue, -1);
        final int speed = a.getInt(R.styleable.ItemPicker_ItemPickerSpeed, -1);
        a.recycle();
        final OnClickListener clickListener = new OnClickListener() {

            @Override
            public void onClick(final View v) {
                validateInput(mText);
                if (!mText.hasFocus())
                    mText.requestFocus();
                // now perform the increment/decrement
                if (R.id.increment == v.getId()) {
                    changeCurrent(mCurrentValue + 1);
                } else if (R.id.decrement == v.getId()) {
                    changeCurrent(mCurrentValue - 1);
                }
            }
        };
        final OnFocusChangeListener focusListener = new OnFocusChangeListener() {

            @Override
            public void onFocusChange(final View v, final boolean hasFocus) {
                /* When focus is lost check that the text field
                 * has valid values.
                 */
                if (!hasFocus) {
                    validateInput(v);
                }
            }
        };
        final OnLongClickListener longClickListener = new OnLongClickListener() {

            /**
             * We start the long click here but rely on the {@link ItemPickerButton}
             * to inform us when the long click has ended.
             */
            @Override
            public boolean onLongClick(final View v) {
                /* The text view may still have focus so clear it's focus which will
                 * trigger the on focus changed and any typed values to be pulled.
                 */
                mText.clearFocus();
                if (R.id.increment == v.getId()) {
                    mIncrement = true;
                    mHandler.post(mRunnable);
                } else if (R.id.decrement == v.getId()) {
                    mDecrement = true;
                    mHandler.post(mRunnable);
                }
                return true;
            }
        };
        final InputFilter inputFilter = new NumberPickerInputFilter();
        mNumberInputFilter = new NumberRangeKeyListener();
        mIncrementButton = findViewById(R.id.increment);
        mIncrementButton.setOnClickListener(clickListener);
        mIncrementButton.setOnLongClickListener(longClickListener);
        mIncrementButton.setNumberPicker(this);
        if (incrementBackground != -1)
            mIncrementButton.setBackgroundResource(incrementBackground);
        if (incrementSrc != -1)
            mIncrementButton.setImageResource(incrementSrc);
        mDecrementButton = findViewById(R.id.decrement);
        mDecrementButton.setOnClickListener(clickListener);
        mDecrementButton.setOnLongClickListener(longClickListener);
        mDecrementButton.setNumberPicker(this);
        if (decrementBackground != -1)
            mDecrementButton.setBackgroundResource(decrementBackground);
        if (decrementSrc != -1)
            mDecrementButton.setImageResource(decrementSrc);
        mText = findViewById(R.id.input);
        mText.setOnFocusChangeListener(focusListener);
        mText.setFilters(new InputFilter[] { inputFilter });
        mText.setRawInputType(InputType.TYPE_CLreplaced_NUMBER);
        if (editTextBackground != -1)
            mText.setBackgroundResource(editTextBackground);
        if (!isEnabled()) {
            setEnabled(false);
        }
        if (minValue > -1 && maxValue > -1) {
            if (displayedValue != null) {
                setRange(minValue, maxValue, displayedValue);
            } else {
                setRange(minValue, maxValue);
            }
        }
        if (currentValue > -1)
            setValue(currentValue);
        if (speed > -1)
            setSpeed(speed);
    }

    /**
     * Set the enabled state of this view. The interpretation of the enabled
     * state varies by subclreplaced.
     *
     * @param enabled True if this view is enabled, false otherwise.
     */
    @Override
    public void setEnabled(final boolean enabled) {
        super.setEnabled(enabled);
        mIncrementButton.setEnabled(enabled);
        mDecrementButton.setEnabled(enabled);
        mText.setEnabled(enabled);
    }

    @Override
    public void setOnKeyListener(final OnKeyListener listener) {
        super.setOnKeyListener(listener);
        mIncrementButton.setOnKeyListener(listener);
        mDecrementButton.setOnKeyListener(listener);
        mText.setOnKeyListener(listener);
    }

    /**
     * Set the callback that indicates the item has been adjusted by the user.
     * @param listener the callback, should not be null.
     */
    public void setOnChangeListener(final OnChangedListener listener) {
        mListener = listener;
    }

    /**
     * Set the formatter that will be used to format the item for presentation
     * @param formatter the formatter object.  If formatter is null, String.valueOf()
     * will be used
     */
    public void setFormatter(final Formatter formatter) {
        mFormatter = formatter;
    }

    /**
     * Set the range of items allowed for the item picker. The current
     * value will be automatically set to the start.
     *
     * @param min the start of the range (inclusive)
     * @param max the end of the range (inclusive)
     */
    public void setRange(final int min, final int max) {
        setRange(min, max, null);
    }

    /**
     * Set the range of items allowed for the item picker. The current
     * value will be automatically set to the start. Also provide a mapping
     * for values used to display to the user.
     *
     * @param min the start of the range (inclusive)
     * @param max the end of the range (inclusive)
     * @param displayedValues the values displayed to the user.
     */
    public void setRange(final int min, final int max, final String[] displayedValues) {
        mDisplayedValues = displayedValues;
        mMinValue = min;
        mMaxValue = max;
        if ((mCurrentValue < min) || (mCurrentValue > max))
            mCurrentValue = min;
        updateView();
        if (displayedValues != null) {
            // Allow text entry rather than strictly numeric entry.
            mText.setRawInputType(InputType.TYPE_CLreplaced_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
        }
    }

    /**
     * Set the current value for the item picker.
     *
     * @param value the current value the start of the range (inclusive)
     * @throws IllegalArgumentException when current is not within the range
     *         of of the item picker
     */
    public void setValue(int value) {
        if (value < mMinValue || value > mMaxValue) {
            /*            throw new IllegalArgumentException(
            	String.format("current(%d) should be >= start(%d) and <= end(%d)",
            		value, mMinValue, mMaxValue)); */
            Log.w("ItemPicker", String.format("current(%d) should be between min(%d) to max(%d) changed to min", value, mMinValue, mMaxValue));
            value = mMinValue;
        }
        mCurrentValue = value;
        updateView();
    }

    /**
     * Sets the speed at which the numbers will scroll when the +/-
     * buttons are longpressed
     *
     * @param speed The speed (in milliseconds) at which the numbers will scroll
     * default 300ms
     */
    public void setSpeed(final long speed) {
        mSpeed = speed;
    }

    private String formatNumber(final int value) {
        return (mFormatter != null) ? mFormatter.toString(value) : String.valueOf(value);
    }

    /**
     * Sets the current value of this ItemPicker, and sets mPrevious to the previous
     * value.  If current is greater than mEnd less than mStart, the value of mCurrent
     * is wrapped around.
     *
     * Subclreplacedes can override this to change the wrapping behavior
     *
     * @param current the new value of the ItemPicker
     */
    protected void changeCurrent(int current) {
        // Wrap around the values if we go past the start or end
        if (current > mMaxValue) {
            current = mMinValue;
        } else if (current < mMinValue) {
            current = mMaxValue;
        }
        mPrevValue = mCurrentValue;
        mCurrentValue = current;
        notifyChange();
        updateView();
    }

    /**
     * Notifies the listener, if registered, of a change of the value of this
     * ItemPicker.
     */
    private void notifyChange() {
        if (mListener != null) {
            mListener.onChanged(this, mPrevValue, mCurrentValue);
        }
    }

    /**
     * Updates the view of this ItemPicker.  If displayValues were specified
     * in {@link #setRange}, the string corresponding to the index specified by
     * the current value will be returned.  Otherwise, the formatter specified
     * in setFormatter will be used to format the number.
     */
    private void updateView() {
        /* If we don't have displayed values then use the
         * current number else find the correct value in the
         * displayed values for the current number.
         */
        if (mDisplayedValues == null) {
            mText.setText(formatNumber(mCurrentValue));
        } else {
            mText.setText(mDisplayedValues[mCurrentValue - mMinValue]);
        }
        mText.setSelection(mText.getText().length());
    }

    private void validateCurrentView(final CharSequence str) {
        final int val = getSelectedPos(str.toString());
        if ((val >= mMinValue) && (val <= mMaxValue)) {
            if (mCurrentValue != val) {
                mPrevValue = mCurrentValue;
                mCurrentValue = val;
                notifyChange();
            }
        }
        updateView();
    }

    private void validateInput(final View v) {
        final String str = String.valueOf(((TextView) v).getText());
        if (TextUtils.isEmpty(str)) {
            // Restore to the old value as we don't allow empty values
            updateView();
        } else {
            // Check the new value and ensure it's in range
            validateCurrentView(str);
        }
    }

    /**
     * @hide
     */
    public void cancelIncrement() {
        mIncrement = false;
    }

    /**
     * @hide
     */
    public void cancelDecrement() {
        mDecrement = false;
    }

    private static final char[] DIGIT_CHARACTERS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

    private ItemPickerButton mIncrementButton;

    private ItemPickerButton mDecrementButton;

    private clreplaced NumberPickerInputFilter implements InputFilter {

        @Override
        public CharSequence filter(final CharSequence source, final int start, final int end, final Spanned dest, final int dstart, final int dend) {
            if (mDisplayedValues == null) {
                return mNumberInputFilter.filter(source, start, end, dest, dstart, dend);
            }
            final CharSequence filtered = String.valueOf(source.subSequence(start, end));
            final String result = String.valueOf(dest.subSequence(0, dstart)) + filtered + dest.subSequence(dend, dest.length());
            final String str = String.valueOf(result).toLowerCase(Locale.US);
            for (String val : mDisplayedValues) {
                val = val.toLowerCase(Locale.US);
                if (val.startsWith(str)) {
                    return filtered;
                }
            }
            return "";
        }
    }

    private clreplaced NumberRangeKeyListener extends NumberKeyListener {

        // XXX This doesn't allow for range limits when controlled by a
        // soft input method!
        @Override
        public int getInputType() {
            return InputType.TYPE_CLreplaced_NUMBER;
        }

        @NonNull
        @Override
        protected char[] getAcceptedChars() {
            return DIGIT_CHARACTERS;
        }

        @Override
        public CharSequence filter(final CharSequence source, final int start, final int end, final Spanned dest, final int dstart, final int dend) {
            CharSequence filtered = super.filter(source, start, end, dest, dstart, dend);
            if (filtered == null) {
                filtered = source.subSequence(start, end);
            }
            final String result = String.valueOf(dest.subSequence(0, dstart)) + filtered + dest.subSequence(dend, dest.length());
            if ("".equals(result)) {
                return result;
            }
            final int val = getSelectedPos(result);
            /* Ensure the user can't type in a value greater
             * than the max allowed. We have to allow less than min
             * as the user might want to delete some numbers
             * and then type a new number.
             */
            if (val > mMaxValue) {
                return "";
            } else {
                return filtered;
            }
        }
    }

    private int getSelectedPos(String str) {
        if (mDisplayedValues == null) {
            try {
                return Integer.parseInt(str);
            } catch (final NumberFormatException e) {
            /* Ignore as if it's not a number we don't care */
            }
        } else {
            for (int i = 0; i < mDisplayedValues.length; i++) {
                /* Don't force the user to type in jan when ja will do */
                str = str.toLowerCase(Locale.US);
                if (mDisplayedValues[i].toLowerCase(Locale.US).startsWith(str)) {
                    return mMinValue + i;
                }
            }
            /* The user might have typed in a number into the month field i.e.
             * 10 instead of OCT so support that too.
             */
            try {
                return Integer.parseInt(str);
            } catch (final NumberFormatException e) {
            /* Ignore as if it's not a number we don't care */
            }
        }
        return mMinValue;
    }

    /**
     * Returns the current value of the ItemPicker
     * @return the current value.
     */
    public int getValue() {
        return mCurrentValue;
    }

    /**
     * Returns the upper value of the range of the ItemPicker
     * @return the uppper number of the range.
     */
    protected int getEndRange() {
        return mMaxValue;
    }

    /**
     * Returns the lower value of the range of the ItemPicker
     * @return the lower number of the range.
     */
    protected int getBeginRange() {
        return mMinValue;
    }
}

18 Source : PinEntryEditText.java
with GNU General Public License v3.0
from qtumproject

@Override
public void setFilters(InputFilter[] filters) {
    super.setFilters(filters);
    mMaxLength = getMaxLength(filters);
    mNumChars = mMaxLength;
    if (mMaxLength > 0) {
        int availableWidth = getWidth() - ViewCompat.getPaddingEnd(this) - ViewCompat.getPaddingStart(this);
        if (mSpace < 0) {
            mCharSize = (availableWidth / (mNumChars * 2 - 1));
        } else {
            mCharSize = (availableWidth - (mSpace * (mNumChars - 1))) / mNumChars;
        }
        mLineCoords = new RectF[(int) mNumChars];
        mCharBottom = new float[(int) mNumChars];
        int startX;
        int bottom = getHeight() - getPaddingBottom();
        int rtlFlag;
        final boolean isLayoutRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;
        if (isLayoutRtl) {
            rtlFlag = -1;
            startX = (int) (getWidth() - ViewCompat.getPaddingStart(this) - mCharSize);
        } else {
            rtlFlag = 1;
            startX = ViewCompat.getPaddingStart(this);
        }
        for (int i = 0; i < mNumChars; i++) {
            mLineCoords[i] = new RectF(startX, bottom, startX + mCharSize, bottom);
            if (mPinBackground != null) {
                if (mIsDigitSquare) {
                    mLineCoords[i].top = getPaddingTop();
                    mLineCoords[i].right = startX + mLineCoords[i].height();
                } else {
                    mLineCoords[i].top -= mTextHeight.height() + mTextBottomPadding * 2;
                }
            }
            if (mSpace < 0) {
                startX += rtlFlag * mCharSize * 2;
            } else {
                startX += rtlFlag * (mCharSize + mSpace);
            }
            mCharBottom[i] = mLineCoords[i].bottom - mTextBottomPadding;
        }
    }
    invalidate();
}

18 Source : UserTextDialog.java
with Apache License 2.0
from pinguo-sunjianfei

private void setMaxLength(int maxLength) {
    InputFilter[] fArray = new InputFilter[1];
    fArray[0] = new InputFilter.LengthFilter(maxLength);
    mEditText.setFilters(fArray);
}

18 Source : UserReviseActivity.java
with Apache License 2.0
from pinguo-sunjianfei

// /////////////////////////////////////
// 工具
private void setMaxLength(int maxLength) {
    InputFilter[] fArray = new InputFilter[1];
    fArray[0] = new InputFilter.LengthFilter(maxLength);
    mEditText.setFilters(fArray);
}

18 Source : MuunTextInput.java
with MIT License
from muun

/**
 * Add an InputFilter to the underlying EditText.
 */
public void addFilter(InputFilter newFilter) {
    // Yes. It's 2018 and this following bit is actually happening.
    final InputFilter[] currentFilters = editText.getFilters();
    final InputFilter[] newFilters = new InputFilter[currentFilters.length + 1];
    System.arraycopy(currentFilters, 0, newFilters, 0, currentFilters.length);
    newFilters[newFilters.length - 1] = newFilter;
    editText.setFilters(newFilters);
}

18 Source : DialerFilter.java
with Apache License 2.0
from lulululbj

/**
 * This widget is a layout that contains several specifically-named child views that
 * handle keyboard entry interpreted as standard phone dialpad digits.
 *
 * @deprecated Use a custom view or layout to handle this functionality instead
 */
@Deprecated
public clreplaced DialerFilter extends RelativeLayout {

    public DialerFilter(Context context) {
        super(context);
    }

    public DialerFilter(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        // Setup the filter view
        mInputFilters = new InputFilter[] { new InputFilter.AllCaps() };
        mHint = (EditText) findViewById(com.android.internal.R.id.hint);
        if (mHint == null) {
            throw new IllegalStateException("DialerFilter must have a child EditText named hint");
        }
        mHint.setFilters(mInputFilters);
        mLetters = mHint;
        mLetters.setKeyListener(TextKeyListener.getInstance());
        mLetters.setMovementMethod(null);
        mLetters.setFocusable(false);
        // Setup the digits view
        mPrimary = (EditText) findViewById(com.android.internal.R.id.primary);
        if (mPrimary == null) {
            throw new IllegalStateException("DialerFilter must have a child EditText named primary");
        }
        mPrimary.setFilters(mInputFilters);
        mDigits = mPrimary;
        mDigits.setKeyListener(DialerKeyListener.getInstance());
        mDigits.setMovementMethod(null);
        mDigits.setFocusable(false);
        // Look for an icon
        mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
        // Setup focus & highlight for this view
        setFocusable(true);
        // XXX Force the mode to QWERTY for now, since 12-key isn't supported
        mIsQwerty = true;
        setMode(DIGITS_AND_LETTERS);
    }

    /**
     * Only show the icon view when focused, if there is one.
     */
    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (mIcon != null) {
            mIcon.setVisibility(focused ? View.VISIBLE : View.GONE);
        }
    }

    public boolean isQwertyKeyboard() {
        return mIsQwerty;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean handled = false;
        switch(keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_ENTER:
            case KeyEvent.KEYCODE_DPAD_CENTER:
                break;
            case KeyEvent.KEYCODE_DEL:
                switch(mMode) {
                    case DIGITS_AND_LETTERS:
                        handled = mDigits.onKeyDown(keyCode, event);
                        handled &= mLetters.onKeyDown(keyCode, event);
                        break;
                    case DIGITS_AND_LETTERS_NO_DIGITS:
                        handled = mLetters.onKeyDown(keyCode, event);
                        if (mLetters.getText().length() == mDigits.getText().length()) {
                            setMode(DIGITS_AND_LETTERS);
                        }
                        break;
                    case DIGITS_AND_LETTERS_NO_LETTERS:
                        if (mDigits.getText().length() == mLetters.getText().length()) {
                            mLetters.onKeyDown(keyCode, event);
                            setMode(DIGITS_AND_LETTERS);
                        }
                        handled = mDigits.onKeyDown(keyCode, event);
                        break;
                    case DIGITS_ONLY:
                        handled = mDigits.onKeyDown(keyCode, event);
                        break;
                    case LETTERS_ONLY:
                        handled = mLetters.onKeyDown(keyCode, event);
                        break;
                }
                break;
            default:
                // mIsQwerty = msg.getKeyIsQwertyKeyboard();
                switch(mMode) {
                    case DIGITS_AND_LETTERS:
                        handled = mLetters.onKeyDown(keyCode, event);
                        // preplaced this throw so the shift state is correct (for example,
                        // on a standard QWERTY keyboard, * and 8 are on the same key)
                        if (KeyEvent.isModifierKey(keyCode)) {
                            mDigits.onKeyDown(keyCode, event);
                            handled = true;
                            break;
                        }
                        // Only check to see if the digit is valid if the key is a printing key
                        // in the TextKeyListener. This prevents us from hiding the digits
                        // line when keys like UP and DOWN are hit.
                        // XXX note that KEYCODE_TAB is special-cased here for
                        // devices that share tab and 0 on a single key.
                        boolean isPrint = event.isPrintingKey();
                        if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE || keyCode == KeyEvent.KEYCODE_TAB) {
                            char c = event.getMatch(DialerKeyListener.CHARACTERS);
                            if (c != 0) {
                                handled &= mDigits.onKeyDown(keyCode, event);
                            } else {
                                setMode(DIGITS_AND_LETTERS_NO_DIGITS);
                            }
                        }
                        break;
                    case DIGITS_AND_LETTERS_NO_LETTERS:
                    case DIGITS_ONLY:
                        handled = mDigits.onKeyDown(keyCode, event);
                        break;
                    case DIGITS_AND_LETTERS_NO_DIGITS:
                    case LETTERS_ONLY:
                        handled = mLetters.onKeyDown(keyCode, event);
                        break;
                }
        }
        if (!handled) {
            return super.onKeyDown(keyCode, event);
        } else {
            return true;
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        boolean a = mLetters.onKeyUp(keyCode, event);
        boolean b = mDigits.onKeyUp(keyCode, event);
        return a || b;
    }

    public int getMode() {
        return mMode;
    }

    /**
     * Change the mode of the widget.
     *
     * @param newMode The mode to switch to.
     */
    public void setMode(int newMode) {
        switch(newMode) {
            case DIGITS_AND_LETTERS:
                makeDigitsPrimary();
                mLetters.setVisibility(View.VISIBLE);
                mDigits.setVisibility(View.VISIBLE);
                break;
            case DIGITS_ONLY:
                makeDigitsPrimary();
                mLetters.setVisibility(View.GONE);
                mDigits.setVisibility(View.VISIBLE);
                break;
            case LETTERS_ONLY:
                makeLettersPrimary();
                mLetters.setVisibility(View.VISIBLE);
                mDigits.setVisibility(View.GONE);
                break;
            case DIGITS_AND_LETTERS_NO_LETTERS:
                makeDigitsPrimary();
                mLetters.setVisibility(View.INVISIBLE);
                mDigits.setVisibility(View.VISIBLE);
                break;
            case DIGITS_AND_LETTERS_NO_DIGITS:
                makeLettersPrimary();
                mLetters.setVisibility(View.VISIBLE);
                mDigits.setVisibility(View.INVISIBLE);
                break;
        }
        int oldMode = mMode;
        mMode = newMode;
        onModeChange(oldMode, newMode);
    }

    private void makeLettersPrimary() {
        if (mPrimary == mDigits) {
            swapPrimaryAndHint(true);
        }
    }

    private void makeDigitsPrimary() {
        if (mPrimary == mLetters) {
            swapPrimaryAndHint(false);
        }
    }

    private void swapPrimaryAndHint(boolean makeLettersPrimary) {
        Editable lettersText = mLetters.getText();
        Editable digitsText = mDigits.getText();
        KeyListener lettersInput = mLetters.getKeyListener();
        KeyListener digitsInput = mDigits.getKeyListener();
        if (makeLettersPrimary) {
            mLetters = mPrimary;
            mDigits = mHint;
        } else {
            mLetters = mHint;
            mDigits = mPrimary;
        }
        mLetters.setKeyListener(lettersInput);
        mLetters.setText(lettersText);
        lettersText = mLetters.getText();
        Selection.setSelection(lettersText, lettersText.length());
        mDigits.setKeyListener(digitsInput);
        mDigits.setText(digitsText);
        digitsText = mDigits.getText();
        Selection.setSelection(digitsText, digitsText.length());
        // Reset the filters
        mPrimary.setFilters(mInputFilters);
        mHint.setFilters(mInputFilters);
    }

    public CharSequence getLetters() {
        if (mLetters.getVisibility() == View.VISIBLE) {
            return mLetters.getText();
        } else {
            return "";
        }
    }

    public CharSequence getDigits() {
        if (mDigits.getVisibility() == View.VISIBLE) {
            return mDigits.getText();
        } else {
            return "";
        }
    }

    public CharSequence getFilterText() {
        if (mMode != DIGITS_ONLY) {
            return getLetters();
        } else {
            return getDigits();
        }
    }

    public void append(String text) {
        switch(mMode) {
            case DIGITS_AND_LETTERS:
                mDigits.getText().append(text);
                mLetters.getText().append(text);
                break;
            case DIGITS_AND_LETTERS_NO_LETTERS:
            case DIGITS_ONLY:
                mDigits.getText().append(text);
                break;
            case DIGITS_AND_LETTERS_NO_DIGITS:
            case LETTERS_ONLY:
                mLetters.getText().append(text);
                break;
        }
    }

    /**
     * Clears both the digits and the filter text.
     */
    public void clearText() {
        Editable text;
        text = mLetters.getText();
        text.clear();
        text = mDigits.getText();
        text.clear();
        // Reset the mode based on the hardware type
        if (mIsQwerty) {
            setMode(DIGITS_AND_LETTERS);
        } else {
            setMode(DIGITS_ONLY);
        }
    }

    public void setLettersWatcher(Texreplacedcher watcher) {
        CharSequence text = mLetters.getText();
        Spannable span = (Spannable) text;
        span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }

    public void setDigitsWatcher(Texreplacedcher watcher) {
        CharSequence text = mDigits.getText();
        Spannable span = (Spannable) text;
        span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }

    public void setFilterWatcher(Texreplacedcher watcher) {
        if (mMode != DIGITS_ONLY) {
            setLettersWatcher(watcher);
        } else {
            setDigitsWatcher(watcher);
        }
    }

    public void removeFilterWatcher(Texreplacedcher watcher) {
        Spannable text;
        if (mMode != DIGITS_ONLY) {
            text = mLetters.getText();
        } else {
            text = mDigits.getText();
        }
        text.removeSpan(watcher);
    }

    /**
     * Called right after the mode changes to give subclreplacedes the option to
     * restyle, etc.
     */
    protected void onModeChange(int oldMode, int newMode) {
    }

    /**
     * This mode has both lines
     */
    public static final int DIGITS_AND_LETTERS = 1;

    /**
     * This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
     *  has removed all possibility of the digits matching, leaving only the letters line
     */
    public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2;

    /**
     * This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
     *  has removed all possibility of the letters matching, leaving only the digits line
     */
    public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3;

    /**
     * This mode has only the digits line
     */
    public static final int DIGITS_ONLY = 4;

    /**
     * This mode has only the letters line
     */
    public static final int LETTERS_ONLY = 5;

    EditText mLetters;

    EditText mDigits;

    EditText mPrimary;

    EditText mHint;

    InputFilter[] mInputFilters;

    ImageView mIcon;

    int mMode;

    private boolean mIsQwerty;
}

18 Source : OTPTextWatcher.java
with MIT License
from KingsMentor

private void setMaxLength(int length) {
    InputFilter[] FilterArray = new InputFilter[1];
    FilterArray[0] = new InputFilter.LengthFilter(length);
    mCardTextInputLayout.getEditText().setFilters(FilterArray);
}

18 Source : FloatingLabelEditTextTest.java
with Apache License 2.0
from james602152002

@Test
public void testInputFilters() {
    InputFilter[] inputFilters = new InputFilter[] { new InputFilter.LengthFilter(1), new InputFilter.AllCaps() };
    customView.setFilters(inputFilters);
    inputFilters = new InputFilter[] { new InputFilter.AllCaps(), new InputFilter.LengthFilter(1) };
    customView.setFilters(inputFilters);
}

18 Source : ReactTextInputPropertyTest.java
with MIT License
from hellochirag

@Test
public void testMaxLength() {
    ReactEditText view = mManager.createViewInstance(mThemedContext);
    InputFilter[] filters = new InputFilter[] { new InputFilter.AllCaps() };
    view.setFilters(filters);
    mManager.setMaxLength(view, null);
    replacedertThat(view.getFilters()).isEqualTo(filters);
}

18 Source : ReactTextInputManager.java
with MIT License
from hellochirag

@ReactProp(name = "maxLength")
public void setMaxLength(ReactEditText view, @Nullable Integer maxLength) {
    InputFilter[] currentFilters = view.getFilters();
    InputFilter[] newFilters = EMPTY_FILTERS;
    if (maxLength == null) {
        if (currentFilters.length > 0) {
            LinkedList<InputFilter> list = new LinkedList<>();
            for (int i = 0; i < currentFilters.length; i++) {
                if (!(currentFilters[i] instanceof InputFilter.LengthFilter)) {
                    list.add(currentFilters[i]);
                }
            }
            if (!list.isEmpty()) {
                newFilters = (InputFilter[]) list.toArray(new InputFilter[list.size()]);
            }
        }
    } else {
        if (currentFilters.length > 0) {
            newFilters = currentFilters;
            boolean replaced = false;
            for (int i = 0; i < currentFilters.length; i++) {
                if (currentFilters[i] instanceof InputFilter.LengthFilter) {
                    currentFilters[i] = new InputFilter.LengthFilter(maxLength);
                    replaced = true;
                }
            }
            if (!replaced) {
                newFilters = new InputFilter[currentFilters.length + 1];
                System.arraycopy(currentFilters, 0, newFilters, 0, currentFilters.length);
                currentFilters[currentFilters.length] = new InputFilter.LengthFilter(maxLength);
            }
        } else {
            newFilters = new InputFilter[1];
            newFilters[0] = new InputFilter.LengthFilter(maxLength);
        }
    }
    view.setFilters(newFilters);
}

18 Source : HashCalculatorFragment.java
with MIT License
from hash-checker

private void validateTextCase() {
    boolean useUpperCase = SettingsHelper.useUpperCase(context);
    InputFilter[] fieldFilters = useUpperCase ? new InputFilter[] { new InputFilter.AllCaps() } : new InputFilter[] {};
    etCustomHash.setFilters(fieldFilters);
    etGeneratedHash.setFilters(fieldFilters);
    if (useUpperCase) {
        TextTools.convertToUpperCase(etCustomHash);
        TextTools.convertToUpperCase(etGeneratedHash);
    } else {
        TextTools.convertToLowerCase(etCustomHash);
        TextTools.convertToLowerCase(etGeneratedHash);
    }
    etCustomHash.setSelection(etCustomHash.getText().length());
    etGeneratedHash.setSelection(etGeneratedHash.getText().length());
}

18 Source : CustomTextView.java
with Apache License 2.0
from googlearchive

@Override
public void setFilters(InputFilter[] filters) {
    super.setFilters(getEmojiTextViewHelper().getFilters(filters));
}

18 Source : RegexEditText.java
with Apache License 2.0
from getActivity

/**
 * 添加筛选规则
 */
public void addFilters(InputFilter filter) {
    if (filter == null) {
        return;
    }
    final InputFilter[] newFilters;
    final InputFilter[] oldFilters = getFilters();
    if (oldFilters != null && oldFilters.length > 0) {
        newFilters = new InputFilter[oldFilters.length + 1];
        // 复制旧数组的元素到新数组中
        System.arraycopy(oldFilters, 0, newFilters, 0, oldFilters.length);
        newFilters[oldFilters.length] = filter;
    } else {
        newFilters = new InputFilter[1];
        newFilters[0] = filter;
    }
    super.setFilters(newFilters);
}

See More Examples