androidemojispannablestringbuilder

How to implement a SpannableStringBuilder where only a certain part is colored?


I need to implement a string that changes the color of some parts of it to highlight it. I need to create something like a hotkey guide that displays the action you could perform by pressing the highlighted number. I used to use Html. from HTML but I've read that it's not fast because of the parsing. I need to run the code on a slow device. This is my current code.

private SpannableStringBuilder spannedTxt(String txt, int count){
        String tagStart = "<p>", tagEnd = "</p>";
        String temp = txt;
        int emojCount = count /2;
        emojCount += 1;

        SpannableStringBuilder ssb = new SpannableStringBuilder();

        for (int i = 0; i < count; i++) {
            SpannableString spannable = new SpannableString(temp);
            Log.d(TAG, "convertToSpan: "+spannable.toString());

            spannable.setSpan(new ForegroundColorSpan(Color.RED),
                    txt.indexOf(tagStart) + tagStart.length(), txt.indexOf(tagEnd),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            ssb.append(spannable);

            temp = temp.replaceFirst(tagStart, "");
            temp = temp.replaceFirst(tagEnd, "");
        }

        return ssb;
    }

What it currently does is change the style of the first substring inside <p> and </p> which is a number. For some reason, the tagStart and tagEnd aren't removed from the final SpannableStringBuilder even though when I logged it shows that the tags are removed.

I used <p> and </p> to know which part is the once that need to be colored. I needed that because the action could also contain numbers and I don't need to recolor those numbers on the action. For example, Action 1 (Press 1). The string also contains emojis between each action and I use the count of those to know how many actions do the string contain.

Simpler explanation:
What I need to make is below

Action 1 (Press <p>1</p>) Action 2 (Press <p>2</p>) to

Action 1 (Press <font color="red">1</font>)&nbsp;&nbsp; Action 2 (Press <font color="red">2</font>)

Something like that using SpannableStringBuilder


Solution

  • So, after some thinking, I found a solution for my problem. I changed a bit of how I create my string for the SpannableStringBuilder.

    Action 1 (Press <p>[1]<p>)    �� ��    Action 2 (Press <p>[2]<p>)    �� ��    Action 3 (Press <p>[3]<p>)
    

    Using the string above, I've modified my code to the code below.

    private SpannableStringBuilder spannedTxt(String txt){
            String tagStart = "<p>";
            String temp = txt;
    
            String[] actTxtArr = txt.split(tagStart);
    
            SpannableStringBuilder ssb = new SpannableStringBuilder();
    
            for (int i = 0; i < actTxtArr.length; i++) {
                String arrTxt = actTxtArr[i];
                SpannableString spannable;
    
                if(arrTxt.contains("[")){
                    arrTxt = arrTxt.replace("[", "");
                    arrTxt = arrTxt.replace("]", "");
    
                    spannable = new SpannableString(arrTxt);
    
                    spannable.setSpan(new ForegroundColorSpan(Color.RED),
                            arrTxt.indexOf(arrTxt), arrTxt.indexOf(arrTxt) + arrTxt.length(),
                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }else{
                    spannable = new SpannableString(arrTxt);
                }
    
                ssb.append(spannable);
            }
    
            return ssb;
        }
    

    Now it works the way I wanted it to be. I hope someone who might need to implement something like the one that I did find this useful.