如何在Edittext中实时输入文字,然后根据正则匹配改变颜色

,当然还有许多逻辑可能需要你在处理处理,这个只能算一个简单版最近在写一个功能,类似于微博的话题,#xx 这种。我们在输入框中输入文字,如果输入了#,那就开始搜索后台服务器。然后给你展示一堆热门的话题 ,你点击,选中,然后高亮显示 或者你自己输入,最后以空格啊特殊符号啊,结束,这个规则可以自己定制。需求来了,先简单分析一波 吧:
1.正则规则,这个简单,根据你们制定的,我这规则是,#号开头,非汉字或者字母数字结束,最多3个话题
所以正则是:"(#(#{0}?[\\u4e00-\\u9fa5A-Za-z0-9]+))"
然后非法限定字符是([\\u4e00-\\u9fa5A-Za-z0-9]+)

2.判断当前输入的是啥,所以肯定得在TextWatch里做文章
onTextChanged 中参数的意思,你得先去了解一波,,before=0 是你往里面加字符串,count=0,是删除字符串,然后对应着判断逻辑就好
3。改变颜色 这里的水有点深,可能是我太菜了。
第一个版本:参考 https://github.com/limedroid/TagEditText,
afterTextChanged里的写法,改吧改吧,能用,但是会有问题,在一些机器的一些输入法中,你输入一个,然后给你来个智能提示,你点了那个提示,就出问题了,或者是各种下划线,不能操作,
然后就是搜啊搜的
第二个参考:https://www.jianshu.com/p/d0dbb3445cc1

然后还有第三,第四,大体上都是 在after里,先removewatch,再加watch,或者用html.fromHtml来改颜色,但是都有问题。
最终版来自于 https://stackoverflow.com/questions/42786493/syntax-highlighting-on-android-edittext-using-span

就不废话了,,直接上代码吧,当然了这个只能算一个简单版,还有许多逻辑需要你自己处理,我项目中后续也改了不少,这里只是提供个思路,重点是如何在edittext中输入然后实时改颜色或者其他span

            public class TagEditText extends AppCompatEditText {

    public String prefixTag = "#";
    private String endTag = "#";
    private String tagRegex = DEF_REGEX;
    public static final String DEF_REGEX = "(#(#{0}?[\\u4e00-\\u9fa5A-Za-z0-9]+))";//字符串中只允许1个#
    public static String ILLEGAL_REGEX = "([\\u4e00-\\u9fa5A-Za-z0-9]+)";

    private int tagColor = Color.parseColor("#1B97AA");


    private boolean isSearch = false;


    List tagList = new ArrayList<>();
    int lastSelction = 0;


    public void setSearchState(boolean isSearch) {
        this.isSearch = isSearch;
    }

    public TagEditText(Context context) {
        super(context);
        initView();
    }

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

    public TagEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }


    private void initView() {
        addTextChangedListener(new TextWatcher() {
            private String mBeafore = "";
            private int deletCount = 0;
            private int deleteStart = 0;

            private int selection = 0;

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                mBeafore = s.toString();
                deletCount = count;
                deleteStart = start;
                selection=getSelectionEnd();
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                selection=getSelectionEnd();
                if (before == 0) {
                  //添加
                    if (s.subSequence(start, start + count).toString().equals(prefixTag)) {
                        Timber.d("---开始搜索");

                        if (getTagList().size() >= 3) {

                            isSearch = false;
                            if (searchListener != null) {
                                searchListener.unSearch();
                            }
                        } else {
                            isSearch = true;
                            if (searchListener != null) {
                                searchListener.search("");
                            }
                        }

                    } else if (s.subSequence(start, start + count).toString().equals(" ") || s.subSequence(start, start + count).toString().equals("\r\n") || s.subSequence(start, start + count).toString().equals("\n") || !check(s.subSequence(start, start + count).toString())) {
                        //空格搜索结束
                        isSearch = false;
                        if (searchListener != null) {
                            searchListener.unSearch();
                        }
                    } else {
                        if (isSearch) {
                            String str = s.toString().substring(s.toString().lastIndexOf(prefixTag) + 1);
                            Timber.d("---搜索%s", str);
                            if (searchListener != null) {
                                searchListener.search(str);
                            }

                        } else {
                            Timber.d("---不搜索");
                            if (searchListener != null) {
                                searchListener.unSearch();
                            }
                        }
                    }
                } else if (count == 0) {
                    Timber.d("----delete");
                    //删除
                    if (getTagList().size() > 3) {
                        isSearch = false;
                        if (searchListener != null) {
                            searchListener.unSearch();
                        }
                        return;
                    }
                    String str = s.toString().substring(s.toString().lastIndexOf(prefixTag) + 1, mBeafore.length() - before);
                    String deleteStr = mBeafore.substring(deleteStart, deleteStart + deletCount);
                    if (isSearch) {
                        if (prefixTag.equals(deleteStr)) {
                            //删除的是#
                            isSearch = false;
                            Timber.d("---不搜索%s", str);
                            if (searchListener != null) {
                                searchListener.unSearch();
                            }
                        } else {
                            Timber.d("---搜索%s", str);

                            if (searchListener != null) {
                                searchListener.search(str);
                            }

                        }
                    } else {

                        if (s.toString().lastIndexOf(prefixTag) < 0) {
                            Timber.d("---不搜索%s", str);

                            isSearch = false;
                            if (searchListener != null) {
                                searchListener.unSearch();
                            }
                            return;
                        }
                        String tempStr = s.toString().substring(s.toString().lastIndexOf(prefixTag), mBeafore.length() - before);
                        Timber.d("----tempStr=%s", tempStr);
                        Pattern pattern = Pattern.compile(tagRegex);
                        Matcher matcher = pattern.matcher(tempStr);
                        String match = "";
                        if (matcher.find()) {
                            match = matcher.group(1);
                            if (match.equals(tempStr)) {
                                Timber.d("---搜索%s", str);
                                isSearch = true;
                                if (searchListener != null) {
                                    searchListener.search(str);
                                }

                            }
                        } else if (tempStr.equals(prefixTag)) {
                            Timber.d("---搜索%s", str);
                            isSearch = true;
                            if (searchListener != null) {
                                searchListener.search(str);
                            }
                        } else {
                            Timber.d("---不搜索%s", str);

                            isSearch = false;
                            if (searchListener != null) {
                                searchListener.unSearch();
                            }
                        }
                    }
                }


            }

            @Override
            public void afterTextChanged(Editable text) {
                if (TextUtils.isEmpty(text)) {
                    isSearch = false;
                    searchListener.unSearch();
                    return;

                }
                removeSpans(text, ForegroundColorSpan.class);

                String textStr = text.toString();

                if (TextUtils.isEmpty(tagRegex)) tagRegex = DEF_REGEX;

                Pattern pattern = Pattern.compile(tagRegex);
                Matcher matcher = pattern.matcher(textStr);

                tagList.clear();
                while (matcher.find()) {
                    if (tagList.size() < 3) {
                        tagList.add(matcher.group(1));
                        text.setSpan(new ForegroundColorSpan(tagColor),
                                matcher.start(),
                                matcher.end(),
                                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }

                }
                if (selection==0){
                    Selection.setSelection(text,text.length());
                }else {
                    Selection.setSelection(text,selection);
                }
            }


        });
    }

    void removeSpans(Editable e, Class type) {
        CharacterStyle[] spans = e.getSpans(0, e.length(), type);
        for (CharacterStyle span : spans) {
            e.removeSpan(span);
        }
    }

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        super.onSelectionChanged(selStart, selEnd);


    }

    /**
     * 设置tag
     *
     * @param prefixTag
     * @param endTag
     */
    public TagEditText tag(String prefixTag, String endTag) {
        if (TextUtils.isEmpty(prefixTag) || TextUtils.isEmpty(endTag)) return this;

        this.prefixTag = prefixTag;
        this.endTag = endTag;

        tagRegex = new StringBuilder("(")
                .append(prefixTag)
                .append(".+?")
                .append(endTag)
                .append(")")
                .toString();
        return this;
    }

    /**
     * 设置标签颜色
     *
     * @param tagColor
     * @return
     */
    public TagEditText tagColor(int tagColor) {
        this.tagColor = tagColor;
        return this;
    }


    /**
     * 追加文本
     *
     * @param text
     */
    public void appendText(String text) {
        if (TextUtils.isEmpty(text)) return;

        SpannableStringBuilder builder = new SpannableStringBuilder(getText());
        builder.append(text);
        setText(builder);
        setSelection(getText().toString().length());
    }


    /**
     * 删除文本[删除最后匹配]
     *
     * @param text
     */
    public void removeText(String text) {
        if (TextUtils.isEmpty(text)) return;

        SpannableStringBuilder builder = new SpannableStringBuilder(getText());
        int pos = text.toString().indexOf(text);
        if (pos > -1) {
            try {
                builder = builder.delete(pos, pos + text.length());
                setText(builder);
            } catch (Exception e) {
            }

        }
    }

    /**
     * 获取标签集合
     *
     * @return
     */
    public List getTagList() {

        ArrayList list = new ArrayList<>();
        for (int i = 0; i < tagList.size(); i++) {
            list.add(tagList.get(i).replace(prefixTag, ""));
        }


        return list;
//        Pattern pattern = Pattern.compile(tagRegex);
//        Matcher matcher = pattern.matcher(getText());
//
//        Set picSet = new HashSet<>();
//        ArrayList tagList = new ArrayList<>();
//
//        while (matcher.find()) {
//            picSet.add(matcher.group(1).replace(prefixTag, "").replace(endTag, ""));
//        }
//
//        tagList.clear();
//        tagList.addAll(picSet);     //去重
//        return tagList;
    }

    public interface OnSearchListener {
        void search(String text);

        void unSearch();

    }

    public OnSearchListener searchListener;

    public void setOnSearchListener(OnSearchListener searchListener) {
        this.searchListener = searchListener;
    }

    public boolean check(String text) {
        Pattern pattern = Pattern.compile(ILLEGAL_REGEX);
        Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {

            return true;
        }

        return false;
    }

}

你可能感兴趣的:(如何在Edittext中实时输入文字,然后根据正则匹配改变颜色)