Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete characters from spannable CharSequence

Tags:

android

I have the following input data in String: "Hello #this# is #sample# text."

It sets background color for all elements between # characters. Here's what I got so far:

public static CharSequence colorBackground(CharSequence text) {

    Pattern pattern = Pattern.compile("#(.*?)#");

    Spannable spannable = new SpannableString( text );
    if( pattern != null )
    {
        Matcher matcher = pattern.matcher( text );
        while( matcher.find() )
        {
            int start = matcher.start();
            int end = matcher.end();
            CharacterStyle span = new BackgroundColorSpan(0xFF404040);
            spannable.setSpan( span, start, end, 0 );
        }
    }
    return spannable;
}

Setting background color works, but placeholder characters # are styled too. How to remove them before returning result, because method ReplaceAll doesn't exist for CharSequence?

I use this function to style TextView rows in ListView. It feels a bit slower in emulator after adding this styling function. Maybe I should approach it in some other way e.g. use a custom TextView with custom draw function?

like image 506
joshas Avatar asked Jan 09 '12 23:01

joshas


1 Answers

This sounded like a fun thing to try to figure out.

The key was SpannableStringBuilder. With SpannableString the text itself is immutable, but with SpannableStringBuilder both the text and the markup can be changed. With that in mind I modified your snippet a little to do what you want:

public static CharSequence colorBackground(CharSequence text) {

    Pattern pattern = Pattern.compile("#(.*?)#");

    SpannableStringBuilder ssb = new SpannableStringBuilder( text );

    if( pattern != null )
    {
        Matcher matcher = pattern.matcher( text );
        int matchesSoFar = 0;
        while( matcher.find() )
        {
            int start = matcher.start() - (matchesSoFar * 2);
            int end = matcher.end() - (matchesSoFar * 2);
            CharacterStyle span = new BackgroundColorSpan(0xFF404040);
            ssb.setSpan( span, start + 1, end - 1, 0 );
            ssb.delete(start, start + 1);
            ssb.delete(end - 2, end -1);
            matchesSoFar++;
        }
    }
    return ssb;
}

I don't have much experience with Spannables in general, and I don't know if the way I've gone about deleting the "#" is the best method, but it seems to work.

like image 153
FoamyGuy Avatar answered Sep 25 '22 19:09

FoamyGuy