SpannableStringBuilder заменяет содержимое регулярным выражением

#java #android #regex #spannablestring #spannablestringbuilder

#java #Android #регулярное выражение #spannablestring #spannablestringbuilder

Вопрос:

У меня есть следующий код, в котором я собираюсь пометить содержимое фигурными скобками SpannableString и удалить фигурные скобки, но это дает неверный результат.

 String text = "the {quic}k brown {fox} jumps {over} the lazy dog. {A Quick} {brow}nfoxjumpsoverthelazydog";

tv.setText(makeSpannable(text, "\{.*?\}"));
public SpannableStringBuilder makeSpannable(String text, String regex) {
    SpannableStringBuilder spannable = new SpannableStringBuilder(text);
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(spannable.toString());
    while (matcher.find()) {
        String word = matcher.group();
        String abbr = word.toString().substring(1, word.length() - 1);
        spannable.setSpan(new ForegroundColorSpan(Color.RED), matcher.start(), matcher.end(),  Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        spannable.replace(matcher.start(), matcher.start()   abbr.length() , abbr);
    }
    return spannable;
}
  

Ввод:

 the {quic}k brown {fox} jumps {over} the lazy dog. {A Quick} {brow}nfoxjumpsoverthelazydog
  

Вывод:
введите описание изображения здесь

Ответ №1:

 String text = "the {quic}k brown {fox} jumps {over} the lazy dog. {A Quick} {brow}nfoxjumpsoverthelazydog";

tv.setText(makeSpannable(text, "\{.*?\}"));

public SpannableStringBuilder makeSpannable(String text, String regex) {

    StringBuffer sb = new StringBuffer();
    SpannableStringBuilder spannable = new SpannableStringBuilder();

    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        sb.setLength(0); // clear
        String group = matcher.group();
        // caution, this code assumes your regex has single char delimiters
        String spanText = group.substring(1, group.length() - 1);
        matcher.appendReplacement(sb, spanText);

        spannable.append(sb.toString());
        int start = spannable.length() - spanText.length();

        spannable.setSpan(new ForegroundColorSpan(Color.RED), start, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    sb.setLength(0);
    matcher.appendTail(sb);
    spannable.append(sb.toString());
    return spannable;
}
  

Комментарии:

1. Спасибо за вашу помощь и ваше драгоценное время, хорошее решение, оно работает как шарм. 🙂

2. Разработчики Android: не путайте android.os.Pattern с java.util.regex.Pattern

3. @крис Ларсон, как можно заменить {quic} k бровь [n] {лиса} перепрыгивает {через} собаку #l # azy. {Быстрый} {бровь} n. Как можно пометить их другим цветом и удалить ограничения? Можете ли вы помочь мне в этом случае?

4. это может помочь решить ваши проблемы использования: gist.github.com/nesquena/f2504c642c5de47b371278ee61c75124 @Шахриарнасимнафи

Ответ №2:

Если вы не против использования html:

 tv.setText(Html.fromHtml(makeStringBuffer(text, regex, Color.RED).toString()));

private StringBuffer makeColoredStringBuffer(String text, String regex, int color) {
    // create a buffer to hold the replaced string
    StringBuffer sb = new StringBuffer();
    // create the pattern matcher
    Matcher m = Pattern.compile(regex).matcher(text);
    // iterate through all matches
    while (m.find()) {
        // get the match
        String word = m.group();
        // remove the first and last characters of the match and surround with html font tag
        String abbr = String.format("<font color='#X'>%s</font>", (0xFFFFFF amp; color), word.substring(1, word.length() - 1));
        // appendReplacement handles replacing within the current match's bounds
        m.appendReplacement(sb, abbr);
    }
    // add any text left over after the final match
    m.appendTail(sb);
    return sb;
}
  

Если вы хотите использовать SpannableString :

 tv.setText(makeColoredSpannable(text, regex, Color.RED));

private SpannableStringBuilder makeColoredSpannable(String text, String regex, int color) {
    // create a spannable to hold the final result
    SpannableStringBuilder spannable = new SpannableStringBuilder();
    // create a buffer to hold the replaced string
    StringBuffer sb = new StringBuffer();
    // create the pattern matcher
    Matcher m = Pattern.compile(regex).matcher(text);
    // iterate through all matches
    while (m.find()) {
        // get the match
        String word = m.group();
        // remove the first and last characters of the match
        String abbr = word.substring(1, word.length() - 1);
        // clear the string buffer
        sb.setLength(0);
        // appendReplacement handles replacing within the current match's bounds
        m.appendReplacement(sb, abbr);
        // append the new colored section to the spannable
        spannable.append(sb);
        spannable.setSpan(new ForegroundColorSpan(color), spannable.length() - abbr.length(), spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    // clear the string buffer
    sb.setLength(0);
    // add any text left over after the final match
    m.appendTail(sb);
    spannable.append(sb);
    return spannable;
}
  

Комментарии:

1. Ваш ответ полезен и спасибо за вашу помощь и время, 🙂

2. разве это не будет дублироваться ответом от @Muhammad?