How to add bulleted list to android application?

后端 未结 17 1297
抹茶落季
抹茶落季 2020-11-29 19:14

I have googled my question but there is not working answer provided. How do add a bulleted list to my textview.

相关标签:
17条回答
  • 2020-11-29 19:54

    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" />
    
    0 讨论(0)
  • 2020-11-29 19:54

    Bulleted list can be simply 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>
    0 讨论(0)
  • 2020-11-29 19:56

    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>
    
    0 讨论(0)
  • 2020-11-29 19:58
    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.
    0 讨论(0)
  • 2020-11-29 19:58

    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();
        }
    
    }
    
    0 讨论(0)
  • 2020-11-29 20:01

    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)
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题