如何在Android应用中添加项目符号列表?

106

如何在我的TextView中添加项目符号列表?


看看这个是否有所帮助:https://dev59.com/yZ3ha4cB1Zd3GeqPPBz1#40991388 - MarGin
17个回答

212

由于不支持ul/li/ol,所以很难实现。 但是,您可以使用以下语法糖来解决:

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

&#8226; 是表示列表标记的 HTML 实体。

更多选项可以在这里找到:http://www.elizabethcastro.com/html/extras/entities.html

有关支持哪些标签的更多信息由 Mark Murphy(@CommonsWare)提供:http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html 使用 Html.fromHtml 加载它。

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

1
感谢您提供commonsware网站的链接,我已经寻找这样的东西有一段时间了! - Norman H
6
请注意,如果你从values/strings.xml获取字符串(使用context.getString(R.string.yourstring);),你需要用_CDATA_包装它:<string name="string_name"><![CDATA[ &#8226; foo<br /> &#8226; bar... ]]></string> - Quentin S.
14
如果一个项目符号中有多行内容,那么这个方法就不起作用了。 - thepoosh
现在似乎支持ul/li标签了。 - hmac

60
  1. browep 以 HTML 方式很好地解释了这个问题。 提供的使用 HTML 实体的解决方案可能会有所帮助。但它仅包括项目符号。如果您的文本换行,缩进将不正确。

  2. 我发现其他解决方案嵌入了 Web 视图。这可能对某些人来说是适当的,但我认为这有点过于复杂...(使用列表视图也是如此。)

  3. 我喜欢 Nelson 的创意方法 :D,但它不允许您向文本视图添加无序列表。

  4. 下面是我的一个无序列表示例,使用 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:

  • 当文本换行后,符号点仍然正确缩进。
  • 在一个TextView实例中,您可以将其他格式化或未格式化的文本组合在一起。
  • 您可以在BulletSpan构造函数中定义缩进的大小。

Negative:

  • 您必须将列表的每个项目保存在单独的字符串资源中。因此,您不能像在HTML中那样舒适地定义列表。

1
这种方法(完全模仿)在2.2上不起作用。最终你只会得到一个子弹点。 - Skone
嗨Skone,它在2.2模拟器和原始的Android构建中都可以工作。我看到一个Android版本,在项目符号和文本之间的空格被忽略了。但是项目符号仍然出现了。 你的项目符号字符串末尾有换行符吗? - Diego Frehner
当您更改TextView中的行间距时,此解决方案无法正常工作。 - Marqs
使用BulletSpan是一个很好的方法,它完美地运作并且非常容易! - Moonbloom
7
以上代码对我有效!我所需要做的就是在xml中的每个字符串末尾添加 "\n"。 - Arhat Baid

43

我发现了一种替代方法...只需复制这个符号 "•" (它是文本),并将其粘贴到您的文本视图中,您可以通过更改textcolor以及所有其他属性(如大小、高度和宽度)来更改此符号的颜色。 :)

您可以在输入时使用快捷方式来获取此符号。

对于Windows

ALT + 7

对于Mac

ALT + 8


3
Alt+7 对我不起作用(也许只是针对Mac或Linux),但复制和粘贴Unicode字符•有效。 - Jon
3
请注意:仅当键盘具有单独的数字键盘时,ALT + 7 才有效。 - Aks4125
如果您将符号粘贴到代码中,即字符串中,请注意非ASCII字符和文件编码的问题(尝试从IntelliJ的右下角更改文件的编码)。更好的方法是使用相应的转义序列(例如\u1234)。 - Gil Vegliach
干得好!!恶棍生活! - williamj949
3
• 就是答案 - user2322082
哈哈!在尝试 Ubuntu 上的这个快捷方式时,我刚刚学会了可以使用 ctrl+alt+[任何数字键] 来控制窗口对齐 :-) - Mohd Zaid

25

可立即使用的 Kotlin 扩展

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
        }
    }
}

用法:

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

颜色和大小:

要更改项目符号的颜色或大小,请使用CustomBulletSpan而不是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)
        }
    }
}

你能否以某种方式改变项目符号的大小以匹配文本大小? - nosh
@NoahTanenholtz,您可以通过更改BulletSpan()参数值来增加项目符号的大小。 - Mikhail Sharin
哦,我以为那是间距。 - nosh
间距增加了,而不是项目符号大小 ): - Sumit Shukla
@SumitShukla 感谢您的评论。我刚刚添加了BulletCustomSpan来进行颜色和大小定制。 - Mikhail Sharin
这是一个很好的解决方案,不需要为具有三个参数的BulletSplan添加if条件。 - Parth Patel

23

受这里各种答案的启发,我创建了一个实用程序类,使此过程变得简单易行。这将创建一个带有文本缩进的项目列表。它具有合并字符串、字符串资源和字符串数组资源的方法。

它将创建一个CharSequence,您可以将其传递给TextView。例如:

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

希望有所帮助。享受吧。

注意:这将使用系统标准的圆点,颜色与文本相同。如果您想要自定义符号,请考虑继承BulletSpan并重写其drawLeadingMargin()方法以绘制所需符号。查看BulletSpan源代码了解其工作原理。

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;
}

}

非常感谢您!我使用了makeBulletList函数,它的效果非常好:D - Aba
真是太棒了!谢谢你) - kulikovman

12

这绝对是最简单的...

<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>

3
这个不会正确地缩进吧?比如说,下一行会在项目符号下面换行。 - nivekmai

5

[2021年10月更新]

注意到我的八年老回答,决定基于最新的Android文档中有关使用HTML标记样式化文本进行更新:

  • 在字符串资源中使用HTML标签(如<ul><li>)。这些标签及其他许多标签都受支持!
  • 如果你没有应用格式,可以通过调用setText()直接设置TextView文本。
  • 这比直接粘贴字符或其十六进制代码更好,如果你想保留多行字符串中的缩进。

我在2013年的旧回答:

可以通过在字符串资源中使用<ul><li>标签来创建项目符号列表。

不要使用 setText(Html.fromHtml(string)) 在代码中设置字符串!只需在xml中正常设置字符串或使用setText(string)。

E.g:

strings.xml 文件

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

_layout.xml文件
它将产生以下结果:
  • 第一个项目
  • 项目2

以下标签可以像这样直接嵌入字符串资源中:
  • <a>(支持属性“href”)
  • <annotation>
  • <b>
  • <big>
  • <font>(支持整数属性“height”、“size”、“fgcolor”和“bicolor”)
  • <i>
  • <li>
  • <marquee>
  • <small>
  • <strike>
  • <sub>
  • <sup>
  • <tt>
  • <u>

you don't need the <ul> - Blundell
7
无法工作。仅支持 <b>、<i> 和 <u> 这些 HTML 标签。请参考 http://developer.android.com/guide/topics/resources/string-resource.html。 - Wooff
1
对我来说完美地工作了!唯一需要做的就是在每行开头加上 \n。例如:\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul> - Jack T
这在我的Dev Studio编辑器中可以工作,但在我的设备上不行!唉... - Jamie

4

使用带有复合可绘制对象的简单TextView。例如:

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

4
我使用的一种选项是使用样式设置项目符号绘制。
<style name="Text.Bullet">
    <item name="android:background">@drawable/bullet</item>
    <item name="android:paddingLeft">10dp</item>
</style>

使用方法:

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

我刚从网上获取了一个小子弹图片作为可绘制对象。在Eclipse的图形布局中,该图形被拉伸到文本下面...与我想要的相距甚远。 - JohnK
1
我认为他的意思是 android:drawableLeft= - Blundell

4
这里有另一个解决方案,不是将列表添加到一个textview中,但我想目标是相同的。它使用TableLayout,只需要XML,并且对于小的有序或无序列表非常简单。下面是我用于此的示例代码,没有一行Java代码。
优点: - 您可以在表格行中放置任何您喜欢的内容,不必是textview。 - 您可以使用它创建项目符号和编号列表,或者其他什么类型的列表。 - 您可以使用padding或layout_weight定义缩进。
缺点:
  • 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>
    

同时还需要考虑样式:

<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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接