android html 转图片,Android富文本编辑器(四):HTML文本转换

在真实的工程开发中,一个富文本编辑器,不是仅仅可以编辑显示,还需要处理富文本的转换与解析,方便传输与存储。一般来说,HTML文本是比较理想的网络传输格式。如何将安卓的span式富文本和HTML文本之间进行互转,是本篇介绍的重点。

首先,介绍富文本转成HTML。我们需要做的,是遍历文本中的span对象,并用合适的html标签来修饰span对象对应的文本。示例代码如下:

public static String convertSpannedToRichText(Spanned spanned) {

List spanList =

Arrays.asList(spanned.getSpans(0, spanned.length(), CharacterStyle.class));

SpannableStringBuilder stringBuilder = new SpannableStringBuilder(spanned);

for (CharacterStyle characterStyle : spanList) {

int start = stringBuilder.getSpanStart(characterStyle);

int end = stringBuilder.getSpanEnd(characterStyle);

if (start >= 0) {

String htmlStyle = handleCharacterStyle(characterStyle,

stringBuilder.subSequence(start, end).toString());

if (htmlStyle != null) {

stringBuilder.replace(start, end, htmlStyle);

}

}

}

return stringBuilder.toString();

}

private static String handleCharacterStyle(CharacterStyle characterStyle, String text) {

if (characterStyle instanceof BoldSpan) {

return String.format("%s", text);

} else if (characterStyle instanceof UrlSpan) {

UrlSpan span = (UrlSpan) characterStyle;

return String.format("%s", span.getValue(), text);

} else if (characterStyle instanceof EmojiSpan) {

EmojiSpan span = (EmojiSpan) characterStyle;

return String.format("\"[%s]\"",

span.getUrl(), span.getName());

} else if (characterStyle instanceof FakeImageSpan) {

FakeImageSpan span = (FakeImageSpan) characterStyle;

return String.format("%5C%22%s%5C%22", span.getValue());

} if (characterStyle instanceof ImageSpan) {

ImageSpan span = (ImageSpan) characterStyle;

return String.format("%5C%22%s%5C%22", TextUtils.isEmpty(span.getUrl()) ?

span.getFilePath() : span.getUrl());

}

return null;

}

注:上述代码在处理一些复杂的span嵌套情况时,可能会有问题。如果要考虑到span嵌套的情况,可能需要全新的思路和写法。后续如果有改进会再更新。

下面介绍如何将HTML转化为安卓富文本。这里使用了一个开源库:TagSoup,来处理Html内容的解析。TagSoup是一个解析HTML的java开源库,一般用作HTML的正则化。TagSoup的介绍可以参考网上其它文章,这里不再赘述。而我们要做的,是实现自己的SAX内容处理器,实现org.xml.sax.ContentHandler接口,并set到TagSoupParser中。具体代码都在:RichTextConvertor这个类中。下面节选几个比较重要的方法:

@Override

public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {

handleStartTag(localName, atts);

}

@Override

public void endElement(String uri, String localName, String qName) throws SAXException {

handleEndTag(localName);

}

@Override

public void characters(char[] ch, int start, int length) throws SAXException {

StringBuilder sb = new StringBuilder();

for (int i = 0; i < length; i++) {

char c = ch[i + start];

sb.append(c);

}

mResult.append(sb);

}

// ****************************************** Handle Tags *******************************************

private void handleStartTag(String tag, Attributes attributes) {

if (tag.equalsIgnoreCase("a")) {

startAHref(attributes);

} else if (tag.equalsIgnoreCase("img")) {

startImg(attributes);

} else if (tag.equalsIgnoreCase("b") || tag.equalsIgnoreCase("strong")) {

start(new Bold());

}

}

private void handleEndTag(String tag) {

if (tag.equalsIgnoreCase("a")) {

endAHref();

} else if (tag.equalsIgnoreCase("b")|| tag.equalsIgnoreCase("strong")) {

end(Bold.class, new BoldSpan());

}

}

private void startAHref(Attributes attributes) {

String href = attributes.getValue("", "href");

int len = mResult.length();

mResult.setSpan(new Href(href), len, len, Spanned.SPAN_MARK_MARK);

}

private void start(Object mark) {

int len = mResult.length();

mResult.setSpan(mark, len, len, Spanned.SPAN_MARK_MARK);

}

private void endAHref() {

int len = mResult.length();

Object obj = getLast(Href.class);

int where = mResult.getSpanStart(obj);

mResult.removeSpan(obj);

if (where != len) {

Href h = (Href) obj;

if (h.mHref != null) {

mResult.setSpan(new UrlSpan(h.mHref),

where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

}

private void end(Class extends Object> kind, Object repl) {

int len = mResult.length();

Object obj = getLast(kind);

int where = mResult.getSpanStart(obj);

mResult.removeSpan(obj);

if (where != len) {

// Note: use SPAN_EXCLUSIVE_EXCLUSIVE, the TemporarySpan will be replaced by a SPAN_EXCLUSIVE_INCLUSIVE span

mResult.setSpan(new TemporarySpan(repl), where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

private Object getLast(Class extends Object> kind) {

/*

* This knows that the last returned object from getSpans()

* will be the most recently added.

*/

Object[] objs = mResult.getSpans(0, mResult.length(), kind);

return objs.length == 0 ? null : objs[objs.length - 1];

}

private void startImg(Attributes attributes) {

int len = mResult.length();

String alt = attributes.getValue("", "alt");

String src = attributes.getValue("", "src");

String classString = attributes.getValue("", "class");

// Unicode Character 'OBJECT REPLACEMENT CHARACTER' (U+FFFC)

// see http://www.fileformat.info/info/unicode/char/fffc/index.htm

mResult.append("\uFFFC");

FakeImageSpan imageSpan = new FakeImageSpan(src);

mResult.setSpan(imageSpan, len, len + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

private static class Bold {

}

这里需要分三种情况进行讨论:

对于img这种标签,我们取出其中的属性,就可以进行替换(有的读者可能发现,在img标签的处理上,我使用了一个叫做FakeImageSpan的类。这时因为在传输、存储过程中,图片都是使用了url远程路径或者本地路径,需要先进行下载或加载,才可以使用真正的ImageSpan进行替换);

对于href这种标签,需要先读取内容,直到出现截止标签,再用真正的URL内容替换掉占位span;

对于b和strong这样的标签,先用占位span占位后,在替换成TemporarySpan,并采用SPAN_EXCLUSIVE_EXCLUSIVE格式。在后面处理完所有输入后,统一替换成相应得span,并采取SPAN_EXCLUSIVE_INCLUSIVE格式,这样后续的输入都会采用相同的格式。具体的处理请参考RichTextConvertor。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值