javaandroidandroid-spannable

Replace certain String with Spans without HTML


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?


Solution

  • 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)