基于uiwebview富文本编辑器实践

背景

近来我们微信念书将写主意换成了基于webview的富文本编辑器,遇到了不少题目,这里我将简朴的引见一下我们在开辟过程当中踩到的坑。

完成富文本编辑器有两个基本思绪:

  1. 基于native完成:比方coretext或许textkit

  2. 基于uiwebview完成

第一种计划,你须要本身去完成许多在webview已很成熟的结果,比方链接,字体加粗,题目,援用款式,列表款式等等,这些的事变量都比较可观,而且另有ios/android两个端的对齐题目。另有一个题目,这个多是我们项目相干的题目,我们在本来还没有许多富文本请求的状况下,在textview上做了一些我们对链接的处置惩罚事变,仅仅这一个方面,当时就以为不是很轻易。

第二种计划,你可以借助webview免却许多在第一种计划内里提到的事变,同时webview相对而言,开源的可供参考的项目也更多一点,不过webview也会存在光标的掌握,css的争执处置惩罚以及兼容性的题目,不过在终究挑选计划的时刻,我们几经衡量,终究挑选了webview的计划

基于webview的富文本编辑器的光标及款式题目

uiwebview完成富文本编辑器,一个大贫苦在于光标的处置惩罚,另一个大贫苦就是css款式的兼容,详细体现为以下几个方面:

  1. 怎样坚持光标在可见地区。

  2. 插进去脸色的时刻uiwebview会失焦题目。

  3. 原生敕令会有bug,须要本身处置惩罚。

  4. 款式的兼容性。

  5. at以及话题的链接处置惩罚。

怎样坚持光标在可见地区

这里有许多状况,如我们在当前可见地区的末了一行的时刻,再举行换行时,光标会跑到可见地区的下面,webview不会把光标地点位置自动转动到可见地区,须要手动触发webview的转动机制.

处理这个题目有两个思绪,一种思绪就是hack native的转动逻辑,对转动举行修改处置惩罚,如许做,能使得webview转动表现的像native一样,然则须要hack的处所会比较多,完成起来可能会踩吭。别的一种思绪就是直接在js内里操纵scrollview,如许相对比较简朴。我们运用的是后者的做法,经由过程监听光标位置的变化,来举行修改,代码以下:

   document.addEventListener("selectionchange", function(e) {
       RE.calculateEditorHeightWithCaretPosition();//改正位置
});

这里改正的详细逻辑是,每次光标位置发生变化时起首盘算当前光标的位置,然后推断当前光标是不是在可见地区范围内,假如不在,那末实行window.scrollTo转动到相应地区。这里有个小点须要注重,就是在推断光标位置的时刻,顶部以及底部的推断有轻微的区分,假如推断光标是在可见地区上面,须要推断光标的顶部是不是在可见地区范围内,假如断光标是在可见地区下面,须要推断光标的底部是不是在可见地区范围内。

这里另有一个题目,在末了一行,换行到新的一行举行输入的时刻,假如是汉字输入,会发生遐想输入条,在还没有肯定输入内容的时刻,uiwebview是不知道你须要的高度的,这个时刻,由于触发了selectionchange,会致使输入时刻,全部界面不停的发抖,因而在这里运用了一个奇技淫巧的计划。我们监听input的输入,并在在webview的末了面,强迫插进去一个空缺的div,使得输入始终是在已有的地区范围内的。

别的牢记不要在js,以及native两头都由scroll的操纵,如许会致使转动的逻辑很杂沓。

插进去脸色,光标的变化

在我们的场景中,插进去脸色会弹出一个脸色面板(这应当也是主流的做法),这个脸色面板会掩盖键盘,如许会致使uiwebview失焦。这就意味着,我们在插进去脸色的时刻,不能直接运用Inserthtml敕令插进去,由于在失焦状态下这个敕令会失效,因而在这里须要手动找到正在操纵的node,手动实行Insertnode的操纵,而且要纪录光标的变化位置,以便退出面板退出后,从新foucus找到准确的光标位置。简朴的伪代码以下代码

 // 这时刻光标直接parent是editor,须要推断光标地点的node的nodeIndex,然后将imgNode 插进去到parent[nodeIndex]之前
            if(currentOffset == currentNode.childNodes.length){
                // 光标在editor末了或许editor内容为空,直接append
                currentNode.appendChild(imgNode);
            }else{
                currentNode.insertBefore(imgNode, currentNode.childNodes[currentOffset]);
            }

然后更新一下当前selection,同时在脸色面板删除脸色的时刻,也须要做相似的操纵。

脸色另有一个题目,就是在webview内里插进去脸色以后,传给背景的时刻,由于ios/android两个平台的脸色当地文件名,款式有所区分,因而要转化成[发愣]这个花样。

原生api的坑

前面在提到webview的长处的时刻说过,webview很吸引人的一个处地点于其供应了许多原生的接口来完成一样款式,然则,真正操纵起来才发明,套路远比我们设想的要深。

举一个简朴的例子你要完成加粗以及作废加粗,那末一个敕令就可以搞定。

 document.execCommand('bold', false, null);

一样的,依据文档的引见,假如假如你想要操纵quote花样,改成一下敕令就好了

document.execCommand('formatBlock', false, "<blockquote>")

但是上面这个敕令只能让你增加援用花样,假如要作废援用花样,你会发明但是并没有卵用,就须要本身别的想办法了。这里有一个哥们关于quote的悲催阅历 ,不过我们末了的处置惩罚计划和他略有不同,我们是经由过程推断当前光标地点的Node是不是是有blockquote标签或许是不是是含有blockquote标签的Node的子node来决定是增加援用照样作废援用,伪代码以下:

if (inQuoteBlock.is) {
        document.execCommand('formatBlock', false, "<div>")
    } else {
        document.execCommand('formatBlock', false, "<blockquote>")
        }

一样的另有题目设置等等都有如许的题目。

款式的兼容性

这个题目发生在多个款式并存的状况,比方援用、题目、序列花样、高亮链接混在一升引会发明种种奇奇怪怪的题目。

以我们遇到的一个援用和高亮链接混用的例子来申明。我们先运用援用花样 blockquote,然后在援用笔墨内里插进去一个a标签,接下来再次输入其他笔墨的时刻,会发明体系帮我们偷偷的加了一个span标签,这个标签有它本身的style,致使背面款式跟前面的不一致了。

再举一个例子,我们开辟的时刻测试发明一个bug,就是当援用、题目、序列花样同时运用到一段笔墨的时刻,会发明体系默默的帮你插进去了一个div标签,这个也会致使一些莫名巧妙的花样题目。

固然另有一些其他奇奇怪怪的题目,这些实际上是css款式的题目,关于这些题目的处置惩罚,要么本身保护一套css花样库,然后不要运用体系的document.execCommand敕令,本身去封装,这个固然是最完整的,然则也是最费事变量的,别的一个要领就是去限制某些组合的可能性,或许对某些场景的场景举行特别处置惩罚,固然这个只是不弥补的计划啦,详细怎么做,取决于运用场景,毕竟我们不是做一个word,所以未必须要斟酌的那末周全。

at以及话题的链接处置惩罚

实在这里就是对webview的链接处置惩罚题目了。以@为例,我们的需求请求点击@以后,天生一个搜刮框,可以搜刮想要@的用户,假如运用textview,我们完整可以在textView的delegate内里,依据当前的位置以及输入的内容举行搜刮,然则webview你是很难去猎取用户一段时间输入的内容的,因而,我们直接运用链接替代,当输入一个@以后就天生一个链接,然后搜刮操纵就在链接中举行(这里有个小技能,假如只是输入一个@字符然后将其变成一个Link,那末光标默许的会处在link的表面,因而接下来的输入,不会成为链接的一部份,因而在这里我们天生的是一个 “@ “加一个空格的链接,并把光标手动挪动到@以后)。不过这里另有一个光标的坑,由于我们挑选一个用户以后须要替代掉已输入的部份,也就是将link内容替代掉,会发明光标会挪动到link的最前面去,光标又乱跳了!所以实在这里还须要本身去挪动光标!

别的这里在举行搜刮的时刻另有个题目,就是在运用体系输入法输入中文的时刻,会涌现遐想输入条(quicktype),假如这个时刻,用户没有挑选输入条的内容,而是直接挑选了用户名举行替代,那末我们会自动将当前的link替代成挑选后的内容,并将光标挪动到Link的背面,然则这个时刻,实在体系输入法的遐想输入还没完毕,因而当用户再次点击输入的时刻,体系会默许找本来最先遐想输入时刻的Node位置,然则由于这个已被我们替代掉了,会找不到,从而使得光标跑到webview的表面去,因而我们还须要在这里经由过程监听compositionupdate,举行修改光标的位置

总结

总得来说,基于webview的富文本,虽然体系帮我们做了许多事变,然则真正实践起来照样会发明题目远比我们设想的多,所以永久不要疑心word开辟那末多年的事变!别的要基于webview做富文本编辑器,那末肯定要对Js有肯定的相识,要不然会发明很鬼头痛!不过关于大多数app而言,实在我们的请求是没那末高的,所以找一个合适本身的webview的开源计划照样能很大的削减本身的事变量。

    原文作者:zachwang
    原文地址: https://segmentfault.com/a/1190000006975161
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞