How to add bulleted list to android application?

AndroidTextview

Android Problem Overview


How do add a bulleted list to my textview?

Android Solutions


Solution 1 - Android

Tough to do as ul/li/ol are not supported. Fortunately you can use this as syntactic sugar:

&#8226; foo<br/>
&#8226; bar<br/>
&#8226; baz<br/>

&#8226; is the html entity for a list bullet more choices are here http://www.elizabethcastro.com/html/extras/entities.html

more about which tags are supported provided by Mark Murphy (@CommonsWare) http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html Load that up with Html.fromHtml

((TextView)findViewById(R.id.my_text_view)).setText(Html.fromHtml(myHtmlString));

Solution 2 - Android

  1. browep explained nice the way over HTML. The provided solution with the html entity can be useful. But it includes only the bullet. If your text wraps, the indent will not be correct.

  2. I found other solutions embedding a web view. That maybe is appropriate for some, but i think its kind of overkill... (The same with using a list view.)

  3. I like the creative approach of Nelson :D, but it does not give you the possibility of adding an unordered list to a text view.

  4. My example of an unordered list with bullets using BulletSpan

     CharSequence t1 = getText(R.string.xxx1);
     SpannableString s1 = new SpannableString(t1);
     s1.setSpan(new BulletSpan(15), 0, t1.length(), 0);
     CharSequence t2 = getText(R.string.xxx2);
     SpannableString s2 = new SpannableString(t2);
     s2.setSpan(new BulletSpan(15), 0, t2.length(), 0);
     textView.setText(TextUtils.concat(s1, s2));
    

Positive:

  • Bullets with correct indent after text wraps.
  • You can combine other formatted or not formatted text in one instance of TextView
  • You can define in the BulletSpan constructor how big the indent should be.

Negative:

  • You have to save every item of the list in a separate string resource. So u can not define your list that comfortable how you could in HTML.

Solution 3 - Android

I have found an alternate.. just copy this bullet " • " (it is a text) and paste in your text view's text, you can change the bullet color by changing the textcolor and as well all other attributes like size, height width... :)

you can use short-cut to get this bullet while typing

for windows > ALT + 7

for mac > ALT + 8

Solution 4 - Android

Inspired by the various answers here, I created a Utility class to make this an easy one liner. This will create a bulleted list with indentation for wrapped text. It has methods for combining strings, string resources and string array resources.

It will create a CharSequence which you can pass to a TextView. For example:

CharSequence bulletedList = BulletListUtil.makeBulletList("First line", "Second line", "Really long third line that will wrap and indent properly.");
textView.setText(bulletedList);

Hope it's helpful. Enjoy.

Note: This will use the system standard bullet, a small circle the same color as the text. If you want a custom bullet, consider subclassing BulletSpan and overriding its drawLeadingMargin() to draw the bullet you want. Take a look at the BulletSpan source for an idea how it works.

public class BulletTextUtil {

/**
 * Returns a CharSequence containing a bulleted and properly indented list.
 *
 * @param leadingMargin In pixels, the space between the left edge of the bullet and the left edge of the text.
 * @param context
 * @param stringArrayResId A resource id pointing to a string array. Each string will be a separate line/bullet-point.
 * @return
 */
public static CharSequence makeBulletListFromStringArrayResource(int leadingMargin, Context context, int stringArrayResId) {
    return makeBulletList(leadingMargin, context.getResources().getStringArray(stringArrayResId));
}

/**
 * Returns a CharSequence containing a bulleted and properly indented list.
 *
 * @param leadingMargin In pixels, the space between the left edge of the bullet and the left edge of the text.
 * @param context
 * @param linesResIds An array of string resource ids. Each string will be a separate line/bullet-point.
 * @return
 */
public static CharSequence makeBulletListFromStringResources(int leadingMargin, Context context, int... linesResIds) {
    int len = linesResIds.length;
    CharSequence[] cslines = new CharSequence[len];
    for (int i = 0; i < len; i++) {
        cslines[i] = context.getString(linesResIds[i]);
    }
    return makeBulletList(leadingMargin, cslines);
}

/**
 * Returns a CharSequence containing a bulleted and properly indented list.
 *
 * @param leadingMargin In pixels, the space between the left edge of the bullet and the left edge of the text.
 * @param lines An array of CharSequences. Each CharSequences will be a separate line/bullet-point.
 * @return
 */
public static CharSequence makeBulletList(int leadingMargin, CharSequence... lines) {
    SpannableStringBuilder sb = new SpannableStringBuilder();
	for (int i = 0; i < lines.length; i++) {
		CharSequence line = lines[i] + (i < lines.length-1 ? "\n" : "");
		Spannable spannable = new SpannableString(line);
        spannable.setSpan(new BulletSpan(leadingMargin), 0, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        sb.append(spannable);
    }
    return sb;
}

}

Solution 5 - Android

Ready-to-use Kotlin extension

fun List<String>.toBulletedList(): CharSequence {
    return SpannableString(this.joinToString("\n")).apply {
        this@toBulletedList.foldIndexed(0) { index, acc, span ->
            val end = acc + span.length + if (index != this@toBulletedList.size - 1) 1 else 0
            this.setSpan(BulletSpan(16), acc, end, 0)
            end
        }
    }
}

Usage:

val bulletedList = listOf("One", "Two", "Three").toBulletedList()
label.text = bulletedList

Colors and size:

To change bullet color or size use CustomBulletSpan instead of BulletSpan

package com.fbs.archBase.ui.spans

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.text.Layout
import android.text.Spanned
import android.text.style.LeadingMarginSpan
import androidx.annotation.ColorInt

class CustomBulletSpan(
        private val bulletRadius: Int = STANDARD_BULLET_RADIUS,
        private val gapWidth: Int = STANDARD_GAP_WIDTH,
        @ColorInt private val circleColor: Int = STANDARD_COLOR
) : LeadingMarginSpan {

    private companion object {
        val STANDARD_BULLET_RADIUS = Screen.dp(2)
        val STANDARD_GAP_WIDTH = Screen.dp(8)
        const val STANDARD_COLOR = Color.BLACK
    }

    private val circlePaint = Paint().apply {
    color = circleColor
        style = Paint.Style.FILL
        isAntiAlias = true
    }

    override fun getLeadingMargin(first: Boolean): Int {
        return 2 * bulletRadius + gapWidth
    }

    override fun drawLeadingMargin(
            canvas: Canvas, paint: Paint, x: Int, dir: Int,
            top: Int, baseline: Int, bottom: Int,
            text: CharSequence, start: Int, end: Int,
            first: Boolean,
            layout: Layout?
    ) {
        if ((text as Spanned).getSpanStart(this) == start) {
            val yPosition = (top + bottom) / 2f
            val xPosition = (x + dir * bulletRadius).toFloat()

            canvas.drawCircle(xPosition, yPosition, bulletRadius.toFloat(), circlePaint)
        }
    }
}

Solution 6 - Android

This is by far the easiest..

<string name="bullet_ed_list">\n\u2022 He has been Chairman of CFL Manufacturers Committee of ELCOMA, the All India Association of Lighting Equipment Manufacturers.
\n\u2022 He has been the President of Federation of Industries of India (FII).</string>

Solution 7 - Android

An option I used was to set the bullet drawable using a style.

<style name="Text.Bullet">
	<item name="android:background">@drawable/bullet</item>
	<item name="android:paddingLeft">10dp</item>
</style>

Usage:

<TextView android:id="@+id/tx_hdr" 
android:text="Item 1" style="@style/Text.Bullet" />

Solution 8 - Android

[Update Oct 2021]

Just noticed my 8-year old answer and decided to update it based on the latest Android documentation for styling text with HTML markup:

  • Use HTML tags like <ul> & <li> in your string resources. These tags & many others are supported!
  • If you aren't applying formatting, you can set TextView text directly by calling setText()
  • This is better than directly pasting the character or it's hexcode if you want to preserve indentation in multi-line strings.

My old answer from 2013:

Bulleted lists can be created by using the <ul> and <li> tags in the string resource.

DO NOT USE setText(Html.fromHtml(string)) to set the string in code! Just set the string normally in xml or by using setText(string).

E.g:

strings.xml file

<string name="str1">
    <ul>
        <li><i>first</i> item</li>
        <li>item 2</li>
    </ul>
</string>


layout.xml file

<TextView
    android:text="@string/str1"
/>


It will produce the following result:

  • first item
  • item 2


Following tags are supported like this (directly embedded in the string resource):

  • <a> (supports attributes "href")
  • <annotation>
  • <b>
  • <big>
  • <font> (supports attributes "height", "size", "fgcolor" and "bicolor", as integers)
  • <i>
  • <li>
  • <marquee>
  • <small>
  • <strike>
  • <sub>
  • <sup>
  • <tt>
  • <u>

Solution 9 - Android

use simple TextView with a compound drawable. For example

<TextView     
    android:text="Sample text"
    android:drawableLeft="@drawable/bulletimage" >
</TextView>

Solution 10 - Android

Here is a bulleted list with a header and a tab in front of each item.

public class BulletListBuilder {
    
    private static final String SPACE = " ";
    private static final String BULLET_SYMBOL = "&#8226";
    private static final String EOL = System.getProperty("line.separator");
    private static final String TAB = "\t";
    
    private BulletListBuilder() {
        
    }
    
    public static String getBulletList(String header, String []items) {
        StringBuilder listBuilder = new StringBuilder();
        if (header != null && !header.isEmpty()) {
            listBuilder.append(header + EOL + EOL);
        }
        if (items != null && items.length != 0) {
            for (String item : items) {
                Spanned formattedItem = Html.fromHtml(BULLET_SYMBOL + SPACE + item);
                listBuilder.append(TAB + formattedItem + EOL);
            }
        }
        return listBuilder.toString();
    }

}

Solution 11 - Android

Here's another solution, not exactly adding a list to one textview, but I guess the goal is the same. It's using TableLayout, that needs only XML and it's really simple for small ordered or unordered lists. Below, sample code I used for this, not a line of code in Java.

Positive:

  • you can put whatever you like in table rows, doesn't have to be a textview
  • you can use it to create bulleted and numbered list or whatever
  • you can define indent using padding or layout_weight

Negative:

  • tedious for very long lists (unless you use some crafty text editor with regex)

  • every list item is store as a separate string resource

         <TableRow
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
    
             >
    
             <TextView
                 style="@style/helpPagePointsStyle"
                 android:layout_weight="0.2"
                 android:text="1." />
    
             <TextView
                 style="@style/helpPagePointsStyle"
                 android:layout_weight="3"
                 android:text="@string/help_points1" />
         </TableRow>
    
         <TableRow
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             >
             <TextView
                 style="@style/helpPagePointsStyle"
                 android:layout_weight="0.2"
                 android:text="2." />
    
             <TextView
                 style="@style/helpPagePointsStyle"
                 android:layout_weight="3"
                 android:text="@string/help_points2" />
         </TableRow>
         <TableRow
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             >
             <TextView
                 style="@style/helpPagePointsStyle"
                 android:layout_weight="0.2"
                 android:text="3." />
             <TextView
                 style="@style/helpPagePointsStyle"
                 android:layout_weight="3"
                 android:text="@string/help_points3" />
         </TableRow>
    
    
     </TableLayout>
    

and the style:

<style name="helpPagePointsStyle">
    <item name="android:layout_width">0dp</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:gravity">left</item>
</style>

Solution 12 - Android

Went completely overkill and made a custom text view.

Use it like this:

<com.blundell.BulletTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="--bullet 1 --bullet two --bullet three --bullet four" />

and the code:

package com.blundell;

import android.content.Context;
import android.text.Html;
import android.util.AttributeSet;
import android.widget.TextView;

public class BulletTextView extends TextView {
    private static final String SPLITTER_CHAR = "--";
    private static final String NEWLINE_CHAR = "<br/>";
    private static final String HTML_BULLETPOINT = "&#8226;";

    public BulletTextView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public BulletTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        checkForBulletPointSplitter();
    }

    private void checkForBulletPointSplitter() {
        String text = (String) getText();
        if (text.contains(SPLITTER_CHAR)) {
            injectBulletPoints(text);
        }
    }

    private void injectBulletPoints(String text) {
        String newLinedText = addNewLinesBetweenBullets(text);
        String htmlBulletText = addBulletPoints(newLinedText);
        setText(Html.fromHtml(htmlBulletText));
    }

    private String addNewLinesBetweenBullets(String text) {
        String newLinedText = text.replace(SPLITTER_CHAR, NEWLINE_CHAR + SPLITTER_CHAR);
        newLinedText = newLinedText.replaceFirst(NEWLINE_CHAR, "");
        return newLinedText;
    }

    private String addBulletPoints(String newLinedText) {
        return newLinedText.replace(SPLITTER_CHAR, HTML_BULLETPOINT);
    }

}

Solution 13 - Android

I find this to be the easiest way, leave the textView as it is in the xml file and use the following java code. it worked perfectly fine for me.

private static final String BULLET_SYMBOL = "&#8226";

@Override
protected void onCreate(Bundle savedInstanceState) 
{
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_tutorial);
	
	TextView tv = (TextView) findViewById(R.id.yourTextView);
	
	tv.setText("To perform this exercise you will need the following: "
						+ System.getProperty("line.separator")//this takes you to the next Line
						+ System.getProperty("line.separator")
						+ Html.fromHtml(BULLET_SYMBOL + " Bed")
						+ System.getProperty("line.separator")
						+ Html.fromHtml(BULLET_SYMBOL + " Pillow"));
}

Solution 14 - Android

For single line text you can simply use drawables:

<TextView
    android:id="@+id/txtData"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableStart="@drawable/draw_bullet_list"
    android:drawablePadding="@dimen/padding_8dp"
    android:text="Hello"
    android:textColor="@color/colorBlack" />

draw_bullet_list.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/colorAccent" />

    <size
        android:width="12dp"
        android:height="12dp" />

</shape>

You can change shape, size,color based on your requirement.

Solution 15 - Android

The two options you have for doing a bulleted list are

  • create the list using html (ul,ol) and load the html into a WebView
  • Load the data into a ListView and set the left drawable of your text view in the list item layout, to a suitable image for the bullet.

Option 1 is the easiest.

Solution 16 - Android

another way to support the missing HTML tags, is by replacing them nicely, as shown here

Solution 17 - Android

If You want to create bullet list with editText structure.

I benefited this references

You can use this bullets

           EditText  edtNoteContent = findViewById(R.id.editText_description_note);            

        edtNoteContent.addTextChangedListener(new TextWatcher(){
            @Override
            public void afterTextChanged(Editable e) {

            }
            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

            }
            @Override
            public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter)
            {
                if (lengthAfter > lengthBefore) {
                    if (text.toString().length() == 1) {
                        text = "◎ " + text;
                        edtNoteContent.setText(text);
                        edtNoteContent.setSelection(edtNoteContent.getText().length());
                    }
                    if (text.toString().endsWith("\n")) {
                        text = text.toString().replace("\n", "\n◎ ");
                        text = text.toString().replace("◎ ◎", "◎");
                        edtNoteContent.setText(text);
                        edtNoteContent.setSelection(edtNoteContent.getText().length());
                    }
                }
            }
        });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser590849View Question on Stackoverflow
Solution 1 - AndroidbrowepView Answer on Stackoverflow
Solution 2 - AndroidDiego FrehnerView Answer on Stackoverflow
Solution 3 - AndroidIshtiaqView Answer on Stackoverflow
Solution 4 - AndroidcottonBallPawsView Answer on Stackoverflow
Solution 5 - AndroidMikhail SharinView Answer on Stackoverflow
Solution 6 - AndroidAmit TumkurView Answer on Stackoverflow
Solution 7 - AndroidNelson RamirezView Answer on Stackoverflow
Solution 8 - AndroidAbhishekView Answer on Stackoverflow
Solution 9 - AndroidNouman HanifView Answer on Stackoverflow
Solution 10 - AndroidMaksim DmitrievView Answer on Stackoverflow
Solution 11 - AndroiddorszView Answer on Stackoverflow
Solution 12 - AndroidBlundellView Answer on Stackoverflow
Solution 13 - Androidfernand bontempsView Answer on Stackoverflow
Solution 14 - AndroidSumit ShuklaView Answer on Stackoverflow
Solution 15 - AndroidRobby PondView Answer on Stackoverflow
Solution 16 - Androidandroid developerView Answer on Stackoverflow
Solution 17 - AndroidYavuz YoldaşView Answer on Stackoverflow