如何在Android上实现富文本编辑器?
使用多种布局布局,每种对应一种HTML格式,比如图片,比如有序列表等。具体实现例子可以参考这个链接。中等和
Evernote的富文本编辑就是这样实现的。总的来说比较复杂。
WebView+JavaScript实现。现在Web上有很多成熟的JavaScript富文本编辑库,比如Squire。你只需要做好它。
WebView和JavaScript的交互就够了(多写点回调函数)。虽然理论上是这样,但是在实现过程中你需要解决WebView的兼容性问题(
Android 4.4及以上不同于4.4以下的WebView内核),以及其他不可预见的问题(比如无法粘贴文本的问题)。
编辑文本+ Span .Android的TextView原生支持粗体、删除线、引用等Span。
,实现简单的富文本编辑需求,可操作性还是比较大的。综合考虑之后,我选择了这种方式来实现自己的需求。
既然决定用EditText+Span来实现,就要对相关的API有所了解。
首先,我们来了解一下Span。Span是一个很强大的概念,有兴趣深造的同学推荐直接看这个翻译。
这里使用了两种主要类型的跨度:
继承自CharacterStyle的Span,如StyleSpan,可以在字符级添加粗体、下划线等。
从ParagraphStyle继承的Span,如QuoteSpan,可以添加对段落级文本的引用。
然后我们需要一个可以把Span的效果设置进去的文本结构(也就是实现了Spannable接口),SpannableStringBuilder。
是个不错的选择,EditText提供的getEditableText()方法也可用。通常只需要getEditableText()
就这么做吧,但是面对一些细节,可以用SpannableStringBuilder预置相应的跨度,然后用原文替换。
设置Span的方式也很简单,你需要调用spanable。setspan (object what,int start,int end,int。
Flags)这个方法就够了,方法中的四个参数解释如下:
对象什么,传入你用的Span对象。
Int start,设置跨度的起始位置。
Int end,设置跨度的结束位置。
Int flags,表示设置Span的范围。
在这里,我将重点关注参数int标志,它接受四种类型的参数,即:
跨越。Span _ inclusive _ exclusive是指在设置Span区域之前输入文本,输入的文本也会受到Span的影响。
的影响。
跨越。Span _ inclusive _ inclusive是指在设置Span的区域前后输入文本,所有输入的文本都服从Span。
的影响。
跨越。Span _ exclusive _ exclusive,这意味着只有当你在设置了Span的区域键入输入文本时,输入文本才会服从Span。
的影响。
跨越。Span _ exclusive _ inclusive是指设置Span区域后输入文本,输入的文本也会受到Span的影响。
的影响。
“受影响”表示您仍将保持您设置的Span的样式,如选择spanned。span _ exclusive _ inclusive。
如果一段文本被设置为粗体,那么该段之后新输入的文本也将是粗体。此处推荐span _ exclusive _ exclusive。
参数,毕竟其他参数相对难以控制,会给用户带来困惑。人们认为,操作代表的行为应该准确无误。
好了,这里我们已经知道如何制作一个富文本编辑器组件,无非就是指定起始位置和结束位置,然后设置相应的跨度。
去做吧。至于设置时采用什么规则,可以自己定制。但只是解决了编辑的问题,还有导入导出的问题。
进口的问题很简单。Android SDK中提供了Html.fromHtml()的方法,可以很容易地将Html字符串转换成需要的字符串。
跨区对象。但是需要注意的是,Html.fromHtml()并不支持所有的Html标签,比如无序列表,所以需要自己实现。
Html。TagHandler接口处理你需要的标签,可以参考这个链接实现对删除线和简单无序列表的支持。
面对粗体、斜体等字符级样式,Html.fromHtml()
自然会解决,该加的地方加换行符,没问题;但面对引用、无序列表等段落级样式,这种方法会增加一个换行符,即两个换行符,相当于多了一个空行。一般来说,人们认为一个人
对应两个
但是如果你有特殊需求,也可以像上面说的那样自己分析,不要用默认的系统。
之前介绍过如何导入,你一定很清楚,一定有对应的Html.toHtml()方法!是的,但不幸的是,这种方法不支持所有跨度。
例如,不支持列表。不过没关系,Html.toHtml()的源代码本身简单易懂,可以借鉴。
这里重点介绍Spannanle的一个接口方法nextspantransfontrol(int start,int limit,class)。
Type),此方法将返回您在指定的文本范围内指定的下一个跨度类型的起始位置。按照这种方法,可以逐层扫描指定的跨度。
不用同时考虑其他类型跨度的影响,非常有用。
最后,尽管如此,导入导出还有一个关键问题,就是导入的内容要和导出的内容一致。目前我很难做到这一点。我只能说应该尽量控制,必要的话需要用正则化来处理导入导出的文本。