Android:如何使用 Html.TagHandler?

新手上路,请多包涵

我正在尝试为留言板构建一个 android 应用程序。为了显示帖子内容的格式化 html,我选择了 TextView 和 Html.fromHtml() 方法。不幸的是,这只涵盖了几个 html 标签。未知标签由实现 TagHandler 的类处理,必须由我自己生成。

现在,我在谷歌上搜索了很多,但找不到此类应该如何工作的示例。让我们考虑一下我有一个 u 标签,用于在一些文本下划线(我知道这已被弃用,但无论如何)。我的 TagHandler 是什么样子的?

它通过以下方式调用:

 public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {

前两个论点很好。我想我必须使用 output.append() 修改输出。但是我如何在此处附加带下划线的内容?

原文由 janoliver 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

所以,我终于自己弄明白了。

 public class MyHtmlTagHandler implements TagHandler {

    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
        if(tag.equalsIgnoreCase("strike") || tag.equals("s")) {
            processStrike(opening, output);
        }
    }

    private void processStrike(boolean opening, Editable output) {
        int len = output.length();
        if(opening) {
            output.setSpan(new StrikethroughSpan(), len, len, Spannable.SPAN_MARK_MARK);
        } else {
            Object obj = getLast(output, StrikethroughSpan.class);
            int where = output.getSpanStart(obj);

            output.removeSpan(obj);

            if (where != len) {
                output.setSpan(new StrikethroughSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }

    private Object getLast(Editable text, Class kind) {
        Object[] objs = text.getSpans(0, text.length(), kind);

        if (objs.length == 0) {
            return null;
        } else {
            for(int i = objs.length;i>0;i--) {
                if(text.getSpanFlags(objs[i-1]) == Spannable.SPAN_MARK_MARK) {
                    return objs[i-1];
                }
            }
            return null;
        }
    }
}

对于您的 TextView,您可以这样称呼它:

 myTextView.setText (Html.fromHtml(text.toString(), null, new MyHtmlTagHandler()));

如果有人需要它。

干杯

原文由 janoliver 发布,翻译遵循 CC BY-SA 4.0 许可协议

这个解决方案在 Android sdk 中找到

android.text.html 。第 596 - 626 行。复制/粘贴

private static <T> Object getLast(Spanned text, Class<T> kind) {
    /*
     * This knows that the last returned object from getSpans()
     * will be the most recently added.
     */
    Object[] objs = text.getSpans(0, text.length(), kind);

    if (objs.length == 0) {
        return null;
    } else {
        return objs[objs.length - 1];
    }
}

private static void start(SpannableStringBuilder text, Object mark) {
    int len = text.length();
    text.setSpan(mark, len, len, Spannable.SPAN_MARK_MARK);
}

private static <T> void end(SpannableStringBuilder text, Class<T> kind,
                        Object repl) {
    int len = text.length();
    Object obj = getLast(text, kind);
    int where = text.getSpanStart(obj);

    text.removeSpan(obj);

    if (where != len) {
        text.setSpan(repl, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
}

要使用,请像这样重写 TagHandler:

 public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {

    if(tag.equalsIgnoreCase("strike") || tag.equals("s")) {

        if(opening){
            start((SpannableStringBuilder) output, new Strike();

        } else {
            end((SpannableStringBuilder) output, Strike.class, new StrikethroughSpan());
        }
    }
}

/*
 * Notice this class. It doesn't really do anything when it spans over the text.
 * The reason is we just need to distinguish what needs to be spanned, then on our closing
 * tag, we will apply the spannable. For each of your different spannables you implement, just
 * create a class here.
 */
 private static class Strike{}

原文由 Chad Bingham 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题