Android EditText:如何通过BulletSpan创建一个空的带圆点的段落?

10
我使用与这个问题相同的标题,因为我认为我的问题非常类似于那个问题,我仔细阅读并测试了被接受的答案,但是对我没有用。让我描述一下我的问题:
我的代码看起来像:
 EditText myEdit = (EditText) this.findViewById(R.id.myedit);
 myEdit.setText("a\nb\n");
 Spannable s = myEdit.getText();
 s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
 s.setSpan(new BulletSpan(30), 2, 3,  Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
 s.setSpan(new BulletSpan(30), 4, 4,  Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
 myEdit.setText(s);

我想要看到的是:

  • a
  • b
  • [我想在这里看到第三个项目,但它没有显示出来]

我尝试使用 Spannable.SPAN_INCLUSIVE_INCLUSIVESpannable.SPAN_INCLUSIVE_EXCLUSIVESpannable.SPAN_EXCLUSIVE_INCLUSIVESpannable.SPAN_EXCLUSIVE_EXCLUSIVE 这些标记,但都没有起作用。

如果我使用以下代码:

EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\nc");
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3,  Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 5,  Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
myEdit.setText(s);

然后我得到了期望的结果:

  • a
  • b
  • c

我正在开发一个富文本编辑器,当用户单击项目符号图标时,我需要显示一个空项目符号,但现在我不确定问题可能是什么,因为我想要创建一个新的空BulletSpan(只有一个点,但没有字符跟随它),但如果span的开始和结束没有字符,那么这个点将不会显示出来。


我目前在做一个关于安卓富文本编辑器的项目:https://github.com/chinalwb/are,如果需要可以参考一下。 - LiuWenbin_NO.
3个回答

13

这是一个不太优美的解决方案,但我没有找到更好的方法 - 尝试在最后添加一个空字符(比如零宽度空格)。 这会产生您想要的结果(至少在视觉上):

public void setBulletText(EditText myEdit, String text) {
        String[] lines = TextUtils.split(text, "\n");
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
        String line = null;
        for (int index = 0; index < lines.length; ++index) {
            line = lines[index];
            int length = spannableStringBuilder.length();
            spannableStringBuilder.append(line);
            if (index != lines.length - 1) {
                spannableStringBuilder.append("\n");
            } else if (TextUtils.isEmpty(line)) {
                spannableStringBuilder.append("\u200B");
            }
            spannableStringBuilder.setSpan(new BulletSpan(30), length, length + 1,
                Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        myEdit.setText(spannableStringBuilder);
    }
结果是: enter image description here 理想情况下,我会创建一个自定义的 EditText 类来在内部追加该字符,但在将文本发送给其他对象时删除它。

1
嗯...是的,我可以想象在子类上有一个getRawText()方法,它返回super.getText()(并保留零宽度空格),然后重写getText()本身以删除该字符。我曾考虑过并拒绝了这个基本想法,但我没有考虑到零宽度空格,因为我考虑的是添加实际的空格。零宽度空格使其更容易接受。您是否遇到过字体不支持该特定Unicode字符的问题?非常感谢! - CommonsWare
目前还没有注意到任何问题,但我也没有进行太多测试。实际上,我不是这个解决方案的忠实拥护者——只是还没有找到更好的替代品。 :/ - Samuil Yanovski
我还没有机会测试这些答案,在赏金宽限期到期之前也不会测试。所有三个答案都涉及将某些东西放在最后一个项目上。在这三个答案中,这个(依我之见)最不可能引入视觉伪影,这就是为什么它获得了赏金的原因。话虽如此,由于我还没有尝试过它们中的任何一个,所以你的情况可能会有所不同。 - CommonsWare
@SamuilYanovski,感谢您的回答,看起来很不错,但我需要花更多时间将其与我的应用程序连接起来,我会回来更新我的状态。同时,非常感谢CommonsWare让我的问题更加明确,以便我可以得到这些答案。我曾经参考过CommonsWare进行富文本编辑器开发,但似乎还有很长的路要走,我正在努力中 :) - LiuWenbin_NO.
很抱歉我来晚了。我进行了测试,它运行得非常好!我将开源我的富文本编辑器,其中包含简单的列表(数字/符号)项编辑、粗体、斜体、下划线、删除线、背景颜色、增加/减少缩进等功能...希望它能对您有所帮助,并且希望您也可以对它进行改进。 - LiuWenbin_NO.

2

这个好吗?

EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\n\n");
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
myEdit.setText(s);
myEdit.setSelection(s.length()-1);

结果是:

在这里输入图片描述

该内容涉及IT技术,意思是显示了一张图片。

如果这取决于setSelection()调用,那就不好,因为如果用户单击其他地方,效果可能会丢失。 - CommonsWare
因为我们是通过编程设置文本的,所以如果没有使用setSelection()方法,光标将会停留在字母'a'的前面。但除此之外,所有三个项目符号都将如上所示。 - krishnakumarp
你可以使用setTextKeepState()方法。 - v4_adi

1
我有一个简单的解决方案,只需在换行符后添加一个空格。
EditText myEdit = (EditText) this.findViewById(R.id.myedit);
myEdit.setText("a\nb\n "); //notice the space after newline
Spannable s = myEdit.getText();
s.setSpan(new BulletSpan(30), 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
s.setSpan(new BulletSpan(30), 2, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
s.setSpan(new BulletSpan(30), 4, 4, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
myEdit.setText(s);

这基本上与Samuil的答案相同,只是他的视觉效果较少。考虑到用户点击“EditText”的方式,您的空格实际上会很明显(例如,用户单击并最终停留在最后一个项目符号处,导致前导空格)。不过还是谢谢! - CommonsWare
我尝试了这段代码,发现空间不明显,即使你点击用户也在正确的位置。 - blganesh101
好的,我会运行一些测试。谢谢! - CommonsWare
好的,当用户将光标拖到下一行时,他可能会留下前导空格。但是点击项目符号时,它会显示在开头。 - blganesh101

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