Android EditText:如何在输入时应用前景色跨度?

7
我试图在EditText中输入文本时为文本应用字体颜色。然而,这非常不一致,有时如果您键入一个空格,那么该空格之前的文本将返回到默认的黑色颜色。或者,如果我把光标放在一个单词的中间并开始输入,整个单词的颜色都会改变,而不仅仅是我正在输入的文本。粗体、斜体和下划线似乎效果很好。如何确保只有我正在输入的文本受到字体颜色的影响?请参见下面的“大小和颜色”注释...
     contentEdit.addTextChangedListener(new TextWatcher() { 
            public void afterTextChanged(Editable s) { 

                //add style as the user types if a toggle button is enabled
                ToggleButton boldButton = (ToggleButton) findViewById(R.id.bold);
                ToggleButton emButton = (ToggleButton) findViewById(R.id.italic);
                ToggleButton underlineButton = (ToggleButton) findViewById(R.id.underline);

                int position = Selection.getSelectionStart(contentEdit.getText());

                try{
                    if (position < 0){
                        position = 0;
                    }

                    if (position > 0){

                        if (styleStart > position || position > (cursorLoc + 1)){
                            //user changed cursor location, reset
                            if (position - cursorLoc > 1){
                                //user pasted text
                                styleStart = cursorLoc;
                            }
                            else{
                                styleStart = position - 1;
                            }
                        }

                        if (boldButton.isChecked()){  
                            StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);

                            for (int i = 0; i < ss.length; i++) {
                                if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
                                    s.removeSpan(ss[i]);
                                }
                            }
                            s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (emButton.isChecked()){
                            StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);

                            for (int i = 0; i < ss.length; i++) {
                                if (ss[i].getStyle() == android.graphics.Typeface.ITALIC){
                                    s.removeSpan(ss[i]);
                                }
                            }
                            s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                        if (underlineButton.isChecked()){
                            UnderlineSpan[] ss = s.getSpans(styleStart, position, UnderlineSpan.class);

                            for (int i = 0; i < ss.length; i++) {
                                s.removeSpan(ss[i]);
                            }
                            s.setSpan(new UnderlineSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }

                        //SIZE AND COLOR//////////////////////////////////////////////////////
                       s.setSpan(new ForegroundColorSpan(m_color), position, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                       s.setSpan(new AbsoluteSizeSpan(m_curSize, true), position, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
                }
                catch(Exception e){
                    //Toast.makeText(m_ctx, m_ctx.gets, Toast.LENGTH_LONG).show();
                    showMessage(R.string.NOTE_WARNING_STYLE,m_utils.MSGTYPE_WARNING);
                }

                cursorLoc = Selection.getSelectionStart(contentEdit.getText());
            }

1
有人吗??这是我一直在寻找答案的东西... - Mike6679
你正在测试哪个版本的Android?最低和目标版本是什么? - Christopher Rucinski
2.2 是最小和目标值。 - Mike6679
你能在模拟器中测试新版本的Android,比如4.0吗?如果还有问题,那就更改最小和目标版本,并再次尝试。我相信setSpan()方法存在问题,它似乎忽略了起始和结束位置。 - Christopher Rucinski
你是否注意到只有这段代码被应用了... s.setSpan(new AbsoluteSizeSpan(m_curSize, true), position, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); 而没有应用 s.setSpan(new ForegroundColorSpan(m_color), position, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); - Christopher Rucinski
感谢您的建议,Christopher。然而,我已经解决了这个问题。 - Mike6679
3个回答

8
你可以使用模式来查找单词,然后对单词应用任何 span。
@Override
public void afterTextChanged(Editable s) {
    Spannable textSpan = s;
    final Pattern pattern = Pattern.compile("\\w+");
    final Matcher matcher = pattern.matcher(textSpan);
    while (matcher.find()) {
        start = matcher.start();
        end = matcher.end();
        textSpan.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.red)), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    }

就是这样,它会突出显示你输入的所有匹配单词。希望能有所帮助。


1
像这样...
public static SpannableString parseActiveReply(String name, String body) {
    SpannableString sp = new SpannableString(name + " " + body);
    // 设置用户名字体加粗、高亮
    sp.setSpan(new ForegroundColorSpan(Color.parseColor("#5FADC7")), 0,
            name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    // sp.setSpan(new ForegroundColorSpan(Color.parseColor("#5FADC7")), 0,
    // 0,
    // Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return sp;
}

名称和正文参数分别代表什么? - Mike6679

1
我将Spannable的起始位置从position改为position - 1
//Color
s.setSpan(new ForegroundColorSpan(m_color), 
          position-1, 
          position, 
          Spannable.SPAN_INCLUSIVE_INCLUSIVE);
//Size
s.setSpan(new AbsoluteSizeSpan(m_curSize, true), 
          position-1, 
          position, 
          Spannable.SPAN_INCLUSIVE_INCLUSIVE);

FYI:将“Spannable 的起始位置从 position 改为 position - 1”允许文本在我输入时着色,但是这种实时样式仍然非常不一致和有缺陷。最终我只是将样式应用于用户高亮的文本,这样可以非常稳定地工作。 - Mike6679

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接