NaN
NaN

Reputation: 3591

Android: colorize matches within string

I want to color all words starting with #, + or @. I found solutions to match words and to color substrings of a SpannableString, but it does not work right. Only the last match gets coloured the other matches stay uncoloured, but I am not able to find the error.

public static SpannableStringBuilder colorTags(Context cxt, String text){
    final Pattern hashtag = Pattern.compile("#\\w+");
    final Pattern at = Pattern.compile("(\\s|\\A)@(\\w+)");
    final Pattern name = Pattern.compile("(\\s|\\A)\\+(\\w+)");

    final SpannableStringBuilder spannable = new SpannableStringBuilder(text);

    final ForegroundColorSpan at_color = new ForegroundColorSpan(cxt.getResources().getColor(R.color.orange));
    final ForegroundColorSpan hash_color = new ForegroundColorSpan(cxt.getResources().getColor(R.color.light_blue));
    final ForegroundColorSpan name_color = new ForegroundColorSpan(cxt.getResources().getColor(R.color.green));

    final Matcher matcher = hashtag.matcher(text);
    final Matcher at_matcher = at.matcher(text);
    final Matcher name_matcher = name.matcher(text);


    while (matcher.find()) {
        spannable.setSpan(
                hash_color, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        );
    }

    while (at_matcher.find()) {
        spannable.setSpan(
                at_color, at_matcher.start(), at_matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        );
    }

    while (name_matcher.find()) {
        spannable.setSpan(
                name_color, name_matcher.start(), name_matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        );
    }
    return spannable;
}

Upvotes: 0

Views: 470

Answers (1)

laune
laune

Reputation: 31290

You need a new object for each span, or else it will be moved and end up on the last span.

while (matcher.find()) {
    ForegroundColorSpan hash_color =
        ForegroundColorSpan(cxt.getResources().getColor(R.color.light_blue));
    spannable.setSpan( hash_color, matcher.start(), matcher.end(),
                       Spanned.SPAN_EXCLUSIVE_EXCLUSIVE );
}

Same for the other loops.

Upvotes: 1

Related Questions