3

原始字符串:

Lorem ##ipsum## dolar ##sit## atem。Lorem ipsum dolar 坐##atem##。

成型后:

Lorem #ipsum dolar #sit atem。Lorem ipsum dolar 坐#atem。

但只有最后一个有我想要的格式。见下图。

代码

private void format() {
    CharSequence text = editContent.getText();

    MovementMethod movementMethod = editContent.getMovementMethod();
    if ((movementMethod == null) || !(movementMethod instanceof LinkMovementMethod))
    {
        editContent.setMovementMethod(LinkMovementMethod.getInstance());
    }

    text = setSpanBetweenTokens(text, "##", new ForegroundColorSpan(0xFF0099FF), new UnderlineSpan(), new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            Toast.makeText(getApplicationContext(), "click", Toast.LENGTH_SHORT).show();
        }
    });

    editContent.setText(text);
}

private static CharSequence setSpanBetweenTokens(CharSequence text, String token, CharacterStyle... characterStyle) {
    int tokenLen = token.length();
    int start = text.toString().indexOf(token) + 1;
    int end = text.toString().indexOf(token, start);

    while (start > -1 && end > -1)
    {
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
        for (CharacterStyle c : characterStyle) {
            spannableStringBuilder.setSpan(c, start, end, 0);
        }

        spannableStringBuilder.delete(end, end + tokenLen);
        spannableStringBuilder.delete(start - 1, start);

        text = spannableStringBuilder;

        start = text.toString().indexOf(token) + 1;
        end = text.toString().indexOf(token, start);
    }

    return text;
}

编辑

我的最终解决方案

private void format() {
    CharSequence text = editContent.getText();

    MovementMethod movementMethod = editContent.getMovementMethod();
    if ((movementMethod == null) || !(movementMethod instanceof LinkMovementMethod))
    {
        editContent.setMovementMethod(LinkMovementMethod.getInstance());
    }

    text = setSpanBetweenTokens(text, "##");

    editContent.setText(text);
}

private static CharSequence setSpanBetweenTokens(CharSequence text, String token) {
    int tokenLen = token.length();
    int start = text.toString().indexOf(token) + 1;
    int end = text.toString().indexOf(token, start);

    while (start > -1 && end > -1)
    {
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);

        spannableStringBuilder.setSpan(new ForegroundColorSpan(0xFF0099FF), start, end, 0);
        spannableStringBuilder.setSpan(new UnderlineSpan(), start, end, 0);
        spannableStringBuilder.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View widget) {
                Log.d("DEBUG", "Click");
            }
        }, start, end, 0);

        spannableStringBuilder.delete(end, end + tokenLen);
        spannableStringBuilder.delete(start - 1, start);

        text = spannableStringBuilder;

        start = text.toString().indexOf(token) + 1;
        end = text.toString().indexOf(token, start);
    }

    return text;
}
4

3 回答 3

4

为每个跨度传递不同的对象:

spannableStringBuilder.setSpan(c, start, end, 0);

您为每个跨度传递相同的对象:

new ForegroundColorSpan(0xFF0099FF)

当 span 对象存在于 spannableStringBuilder 中时,它只会更改边界,不会添加新的 span。

于 2012-04-02T10:09:21.153 回答
3

我会建议一个更简单的方法。如果您的格式化需求是基本的,一个简单的正则表达式 + Html.fromHtml() 应该可以解决问题:

private void format() {
    String mText = editContent.getText();

    Spanned mSpannedText = Html.fromHtml(mText.replaceAll("##(.*?)##)","<font color=\"0xFF0099\">#$1</font>"), 

    editContent.setText(mSpannedText);
}
于 2012-04-02T10:11:15.250 回答
1

最终解决方案正确循环但是您的第一个令牌不会像您使用的那样被正确删除

int start = text.toString().indexOf(token) + 1;

仅当您的令牌长度为 1 个字符时才有效。由于您选择的令牌是 ## 更改上面的代码以利用已经创建的变量 tokenLen

int start = text.toString().indexOf(token) + tokenLen;

这将确保您的文本得到正确编辑,并且您的标记的所有痕迹都被删除。

于 2013-06-09T19:48:13.473 回答