- ·上一篇文章:免费实时对话翻译软件“翻译君”上线 打造同声传译般流畅快感
- ·下一篇文章:微信成语猜猜看侍郎怎么过?成语猜猜看侍郎答案汇总
基于uiwebview的富文本编辑器实践
背景最近我们微信读书将写想法换成了基于webview的富文本编辑器,遇到了不少问题,这里我将简单的介绍一下我们在开发过程中踩到的坑。实现富文本编辑器有两个基本思路:第一种方案,你需要自己去实现很多在webview已经很成熟的效果,比如链接,字体加粗,标题,引用样式,列表样式等等,这些的工作量都比较可观,而且还有ios/android两个端的对齐问题。还有一个问题,这个可能是我们项目相关的问题,我们在原来还没有很多富文本要求的情况下,在textview上做了一些我们对链接的处理工作,仅仅这一个方面,当时就觉得不是很方便。第二种方案,你可以借助webview省掉很多在第一种方案里面提到的工作,同时webview相对而言,开源的可供参考的项目也更多一点,不过webview也会存在光标的控制,css的冲突处理以及兼容性的问题,不过在最终选择方案的时候,我们几经权衡,最终选择了webview的方案基于webview的富文本编辑器的光标及样式问题uiwebview实现富文本编辑器,一个大麻烦在于光标的处理,另一个大麻烦就是css样式的兼容,具体体现为如下几个方面:如何保持光标在可见区域这里有很多情况,如我们在当前可见区域的最后一行的时候,再进行换行时,光标会跑到可见区域的下面,webview不会把光标所在位置自动滚动到可见区域,需要手动触发webview的滚动机制.解决这个问题有两个思路,一种思路就是hack native的滚动逻辑,对滚动进行修正处理,这样做,能使得webview滚动表现的像native一样,但是需要hack的地方会比较多,实现起来可能会踩吭。另外一种思路就是直接在js里面操作scrollview,这样相对比较简单。我们使用的是后者的做法,通过监听光标位置的变化,来进行修正,代码如下:这里矫正的具体逻辑是,每次光标位置发生变化时首先计算当前光标的位置,然后判断当前光标是否在可见区域范围内,如果不在,那么执行window.scrollTo滚动到响应区域。这里有个小点需要注意,就是在判断光标位置的时候,顶部以及底部的判断有稍微的区别,如果判断光标是在可见区域上面,需要判断光标的顶部是否在可见区域范围内,如果断光标是在可见区域下面,需要判断光标的底部是否在可见区域范围内。这里还有一个问题,在最后一行,换行到新的一行进行输入的时候,如果是汉字输入,会产生联想输入条,在还没有确定输入内容的时候,uiwebview是不知道你需要的高度的,这个时候,由于触发了selectionchange,会导致输入时候,整个界面不断的抖动,因此在这里使用了一个奇技淫巧的方案。我们监听input的输入,并在在webview的最后面,强制插入一个空白的div,使得输入始终是在已有的区域范围内的。另外切记不要在js,以及native两端都由scroll的操作,这样会导致滚动的逻辑很混乱。插入表情,光标的变化在我们的场景中,插入表情会弹出一个表情面板(这应该也是主流的做法),这个表情面板会覆盖键盘,这样会导致uiwebview失焦。这就意味着,我们在插入表情的时候,不能直接使用Inserthtml命令插入,因为在失焦状态下这个命令会失效,因此在这里需要手动找到正在操作的node,手动执行Insertnode的操作,并且要记录光标的变化位置,以便退出面板退出后,重新foucus找到正确的光标位置。简单的伪代码如下代码然后更新一下当前selection,同时在表情面板删除表情的时候,也需要做类似的操作。表情还有一个问题,就是在webview里面插入表情之后,传给后台的时候,因为ios/android两个平台的表情本地文件名,样式有所区别,因此要转化成[发呆]这个格式。原生api的坑前面在提到webview的优点的时候说过,webview很吸引人的一个地方在于其提供了很多原生的接口来实现一样样式,但是,真正操作起来才发现,套路远比我们想象的要深。举一个简单的例子你要实现加粗以及取消加粗,那么一个命令就能搞定。同样的,按照文档的介绍,如果如果你想要操作quote格式,改成一下命令就好了然而上面这个命令只能让你添加引用格式,如果要取消引用格式,你会发现然而并没有卵用,就需要自己另外想办法了。这里有一个哥们对于quote的悲催经历 ,不过我们最后的处理方案和他略有不同,我们是通过判断当前光标所在的Node是不是有blockquote标签或者是不是含有blockquote标签的Node的子node来决定是添加引用还是取消引用,伪代码如下:同样的还有标题设置等等都有这样的问题。样式的兼容性这个问题发生在多个样式并存的情况,比如引用、标题、序列格式、高亮链接混在一起用会发现各种奇奇怪怪的问题。以我们碰到的一个引用和高亮链接混用的例子来说明。我们先使用引用格式 blockquote,然后在引用文字里面插入一个a标签,接下来再次输入其他文字的时候,会发现系统帮我们偷偷的加了一个span标签,这个标签有它自己的style,导致后面样式跟前面的不一致了。再举一个例子,我们开发的时候测试发现一个bug,就是当引用、标题、序列格式同时运用到一段文字的时候,会发现系统默默的帮你插入了一个div标签,这个也会导致一些莫名奇妙的格式问题。当然还有一些其他奇奇怪怪的问题,这些其实是css样式的问题,对于这些问题的处理,要么自己维护一套css格式库,然后不要使用系统的document.execCommand命令,自己去封装,这个当然是最彻底的,但是也是最费工作量的,另外一个方法就是去限定某些组合的可能性,或者对某些场景的场景进行特殊处理,当然这个只是不补救的方案啦,具体怎么做,取决于使用场景,毕竟我们不是做一个word,所以未必需要考虑的那么全面。at以及话题的链接处理其实这里就是对webview的链接处理问题了。以@为例,我们的需求要求点击@之后,生成一个搜索框,能够搜索想要@的用户,如果使用textview,我们完全能够在textView的delegate里面,根据当前的位置以及输入的内容进行搜索,但是webview你是很难去获取用户一段时间输入的内容的,因此,我们直接使用链接代替,当输入一个@之后就生成一个链接,然后搜索操作就在链接中进行(这里有个小技巧,如果只是输入一个@字符然后将其变成一个Link,那么光标默认的会处在link的外面,因此接下来的输入,不会成为链接的一部分,因此在这里我们生成的是一个 "@ "加一个空格的链接,并把光标手动移动到@之后)。不过这里还有一个光标的坑,因为我
基于uiwebview的富文本编辑器实践