编辑时在 EditText 中保留双色文本块

Keep two-colored text blocks in EditText while editing

我正在尝试用两个不同颜色的文本块创建一个 EditText

String strText = txtEditText.getText().toString();
String strFrontPart = strText.substring(0, FRONT_PART_COUNT);
String strBackPart = strText.substring(FRONT_PART_COUNT);
String text = "<font color=#ffffff>" + strFrontPart + "</font>";
text += "<font color=#000000>" + strBackPart + "</font>";
txtEditText.setText(Html.fromHtml(text));

上面的代码成功地将前面的 FRONT_PART_COUNT 个字符转换为白色字符,其余字符转换为黑色。

我的问题是如何在编辑 EditText 时实现这一点?

我显然不能把它放在afterTextChanged()中,因为它会导致无限递归调用。

在这种情况下,使用 TextWatcher 将是最好的主意(具体来说, afterTextChanged(Editable s) 方法),因为它可以在 [=12= 中编辑后对文本执行修改].

然后你可以通过将它作为参数传递给txtEditText.addTextChangedListener(TextWatcher t)来添加它。

关于 TextWatcher 的更多信息: http://developer.android.com/reference/android/text/TextWatcher.html

您可以使用 afterTextChanged 处理程序中 Editable 参数的 setSpan 方法来完成。

样本:

EditText editText
editText.addTextChangedListener(new TextWatcher() {

    final ForegroundColorSpan red = new ForegroundColorSpan(Color.rgb(255, 0, 0));

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

    }

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

    }

    @Override public void afterTextChanged(Editable s) {
        int max = 2;
        if(s.length() < max) max = s.length();
        s.setSpan(red, 0, max, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    }
});

前两个字母为红色。

    mBugDescription = (EditText) findViewById(R.id.bug_description);
    mWhiteSpan = new ForegroundColorSpan(0xFFFFFFFF);
    mBlackSpan = new ForegroundColorSpan(0xFF000000);

    mBugDescription.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {
            if(s.length() > 0) {
                int FRONT_PART_COUNT = 10;

                s.setSpan(mWhiteSpan, 0, Math.min(s.length(), FRONT_PART_COUNT), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                if(s.length() > FRONT_PART_COUNT){
                    s.setSpan(mBlackSpan, FRONT_PART_COUNT + 1, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
        }
    });