Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: using Spannable for putting text with bullets into TextView

I need to put some text in a several languages. The text looks like:

Title

  • one
  • two
  • three

Anouther Title

  • one
  • two
  • three

Bullets have different colour than anouther text.

I heared about Spannable in Android, but unfortunaly I can use span only with from and end int values. The problem in that that in different languages my words will have different positions, and so spannable text is not for me. Could you help me to solve this in easy way.

like image 651
Near1999 Avatar asked Nov 03 '15 17:11

Near1999


2 Answers

I got so sick of dealing with bulleted text that I wrote a TextView subclass I call BulletTextView.

I have texts in the resource file, as you do. I formatted all the texts to use the Unicode bullet character \u2022 to mark the bullets. So a sample text might look like this:

<string name="product_description_text">Our product is absolutely amazing, because 
    it has these features:
    \n\n\u2022 First awesome feature
    \n\u2022 Second awesome feature
    \n\u2022 Third awesome feature
    \n\n(Note that users with a free trial license can\'t access these features.)\n</string>

BulletTextView overrides TextView.setText() to scan the text for the bullet characters, remove them and save the positions to mark the bulleted spans:

@Override
public void setText(CharSequence text, BufferType type) {

    StringBuilder sb = new StringBuilder();
    List<Integer> markers = new ArrayList<Integer>();

    for (int i = 0; i < text.length(); i++) {
        char ch = text.charAt(i);

        switch (ch) {

        case '\u2022':

            // we found a bullet, mark the start of bullet span but don't append the bullet char
            markers.add(sb.length());

            // ... I do some other stuff here to skip whitespace etc.
            break;

        case '\n':

            // we found a newline char, mark the end of the bullet span
            sb.append(ch);
            markers.add(sb.length());

            // ... I do some stuff here to weed out the newlines without matching bullets

            break;

        // ... I have some special treatment for some other characters,
        //     for instance, a tab \t means a newline within the span

        default:
            // any other character just add it to the string
            sb.append(ch);
            break;
        }
    }

    // ... at the end of the loop I have some code to check for an unclosed span

    //  create the spannable to put in the TextView
    SpannableString spannableString = new SpannableString(sb.toString());

    // go through the markers two at a time and set the spans
    for (int i = 0; i < markers.size(); i += 2) {
        int start = markers.get(i);
        int end = markers.get(i+1);
        spannableString.setSpan(new BulletSpan(gapWidth), start, end, Spannable.SPAN_PARAGRAPH);
    }

    super.setText(spannableString, BufferType.SPANNABLE);
}

I left out some code that was specific to my application, but this is the basic framework for solving your problem.

Not sure about making your bullet a different color, but there is a BulletSpan constructor public BulletSpan(int gapWidth, int color) that may do the trick.

I tried to figure out how to use LineHeight to make larger lines to separate the bullet paragraphs, but I couldn't make it work. I just use a newline to separate the two bullet sections.

like image 156
kris larson Avatar answered Nov 04 '22 01:11

kris larson


Native Android TextView doesn't support HTML ul/li elements (bullet lists). So, two (or more) options you would have:

  • Using workarounds with native TextView.
  • Using 3rd party libraries. For example html-textview fits your requirement.

    Examples of html-textview.

like image 2
frogatto Avatar answered Nov 04 '22 00:11

frogatto