Replace certain String with Spans without HTML

289 views Asked by At

I'm trying to replace a certain string with a span.

For example I have this String:

String s = "redHello greenWorld";

I wanna replace "red" with:

modifiedText.setSpan(new ForegroundColorSpan(Color.parseColor("#FF0000")), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

and "green" with:

modifiedText.setSpan(new ForegroundColorSpan(Color.parseColor("#00FF00")), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

So I create modifiedText this way:

Spannable modifiedText = new SpannableString(s);

How can I replace a certain String with a Span without HTML?

2

There are 2 answers

8
Der Keeper On BEST ANSWER

Since you asked about cutting out - I hope this is what you meant (new code)

//setup
String text = "redHello greenWorld redTest";
List<String> colors = new ArrayList<>();
colors.add("red");
colors.add("green");

//finding the positions
List<Integer> pos = new ArrayList<>();
List<String> colorPositions = new ArrayList<>();
for (String toFind: colors) {
    Pattern word = Pattern.compile(toFind);
    Matcher match = word.matcher(text);
    while (match.find()) {
       pos.add(match.start());
       colorPositions.add(toFind);
    }
}

//replacing
for (String element : colors) {
    text = text.replace(element, "");
}

Now you need to sort the list

//really inefficient sorting
boolean sorted = false;
Integer temp_pos;
String temp_color;
Integer[] sorted_pos = pos.toArray(Integer[]::new);
String[] sorted_color = colorPositions.toArray(String[]::new);
while(!sorted) {
    sorted = true;
    for (int i = 0; i < sorted_pos.length - 1; i++) {
        if (sorted_pos[i] > sorted_pos[i + 1]) {
            temp_pos = sorted_pos[i];
            temp_color = sorted_color[i];
            sorted_pos[i] = sorted_pos[i + 1];
            sorted_color[i] = sorted_color[i + 1];
            sorted_pos[i + 1] = temp_pos;
            sorted_color[i + 1] = temp_color;
            sorted = false;
        }
    }
}

And subtract the "red" and "green"

//subtracting
for (int i = 1; i < sorted_pos.length; i++) {
    for (int j = i; j < sorted_pos.length; j++) {
        sorted_pos[j] -= sorted_color[i - 1].length();
    }
}

The end result now contains [0, 6, 12], the starting indexes of the spans - now you only need to iterate through the output and set the spans (the colors to the spans are in sorted_color)

3
Toygur Ziya Kutlu On

SpannableString doesn't split (substring) the given String. It just changes attributes for given range with start and end index. If you want to change color of some part of a String you don't need substring (or cut). Just use start and end index for which part you want to change and the rest will remain same (original). In your case according to your question you want to change color of red and green words so just use 2 setSpan methods with start and end index of for those words.

String s = "redHello greenWorld";
SpannableString modifiedText = new SpannableString(s);

//Change the color for 'red' word
modifiedText.setSpan(new ForegroundColorSpan(Color.parseColor("#FF0000")), 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

//Change the color for 'green' word
modifiedText.setSpan(new ForegroundColorSpan(Color.parseColor("#00FF00")), 9, 14, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Eventhough it's SpannableString it's still String so you can use it like a String if you want to set as a Text for your View. For example if you want to set that String to your TextView use setText() method with your SpannableString.

textView.setText(modifiedText);