有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在安卓中使用带正则表达式的SpannableString?

我正在尝试使用以下函数在Android中使用spannableString和正则表达式为字符串的一部分着色:

public static String StringReplace(String source) {
        String find = "ABC";
        SpannableString replace = new SpannableString(find);        
        replace.setSpan(new ForegroundColorSpan(Color.RED), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);

        String output = source.replace(find, replace);
        return  output;
    }

因为函数replace()返回一个字符串,所以我无法获得彩色字符串。我的问题是:使用regexp为文本的一部分着色的最佳方法是什么


共 (2) 个答案

  1. # 1 楼答案

    这里有一个课程可以帮助您:

    public class Replacer {
        private final CharSequence mSource;
        private final CharSequence mReplacement;
        private final Matcher mMatcher;
        private int mAppendPosition;
        private final boolean mIsSpannable;
    
        public static CharSequence replace(CharSequence source, String regex,
                CharSequence replacement) {
    
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(source);
            return new Replacer(source, matcher, replacement).doReplace();
        }
    
        private Replacer(CharSequence source, Matcher matcher,
                CharSequence replacement) {
            mSource = source;
            mReplacement = replacement;
            mMatcher = matcher;
            mAppendPosition = 0;
            mIsSpannable = replacement instanceof Spannable;
        }
    
        private CharSequence doReplace() {
            SpannableStringBuilder buffer = new SpannableStringBuilder();
            while (mMatcher.find()) {
                appendReplacement(buffer);
            }
            return appendTail(buffer);
        }
    
        private void appendReplacement(SpannableStringBuilder buffer) {
            buffer.append(mSource.subSequence(mAppendPosition, mMatcher.start()));
            CharSequence replacement = mIsSpannable
                    ? copyCharSequenceWithSpans(mReplacement)
                    : mReplacement;
            buffer.append(replacement);
    
            mAppendPosition = mMatcher.end();
        }
    
        public SpannableStringBuilder appendTail(SpannableStringBuilder buffer) {
            buffer.append(mSource.subSequence(mAppendPosition, mSource.length()));
            return buffer;
        }
    
        // This is a weird way of copying spans, but I don't know any better way.
        private CharSequence copyCharSequenceWithSpans(CharSequence string) {
            Parcel parcel = Parcel.obtain();
            try {
                TextUtils.writeToParcel(string, parcel, 0);
                parcel.setDataPosition(0);
                return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
            } finally {
                parcel.recycle();
            }
        }
    }
    

    还有一个用法示例:

    CharSequence modifiedText = Replacer.replace("ABC aaa AB ABC aa ad ABC", "ABC",
        Html.fromHtml("<font color=\"red\">CBA</font>"));
    textView.setText(modifiedText);
    
  2. # 2 楼答案

    于9月10日更新-更改所有出现的目标字符串

    类似这样的通用方法将起作用:

    public class SpanTest extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            String dispStr = "This has the string ABCDEF in it \nSo does this :ABCDEF - see!\nAnd again ABCD here";
            TextView tv = (TextView) findViewById(R.id.textView1);
            tv.setText(dispStr);
            changeTextinView(tv, "ABC", Color.RED);
        }
    
        private void changeTextinView(TextView tv, String target, int colour) {
            String vString = (String) tv.getText();
            int startSpan = 0, endSpan = 0;
            Spannable spanRange = new SpannableString(vString);
    
            while (true) {
                startSpan = vString.indexOf(target, endSpan);
                ForegroundColorSpan foreColour = new ForegroundColorSpan(colour);
                // Need a NEW span object every loop, else it just moves the span
                if (startSpan < 0)
                    break;
                endSpan = startSpan + target.length();
                spanRange.setSpan(foreColour, startSpan, endSpan,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            tv.setText(spanRange);
        }
    
    }