IOS - WebView富文本开发

作者: 囧rg | 来源:发表于2018-02-23 17:31 被阅读1171次

    前言

    最近开发基于Web版的富文本,要实现PC与移动端互通,而且还有一些基础的操作,故而参考了许多开源框架和富文本JS框架。
    实现富文本技术主要分为三类:ceretext、textkit、webview。这三类各有优劣,开发的难度、方式、用户体验也是有非常大的不同,这里不详细说明,具体的可以找度娘。
    这里我主要使用的基于webview富文本框架:ZSSRichTextEditor,再此基础上进行的改造和开发。

    技术实现

    在ZSSRichTextEditor框架中,有很多的文件,猛地一看有些不知所措。仔细阅读后才发现,主要的文件只有4个,其他的基本都是UI及一些交互。

    • ZSSRichTextEditor.js
    • zsseditor.html
    • JSBeautifier.js(其中style_html方法还没有用)
    • jQuery.js
      在 ZSSRichTextEditor.js 文件中,使用的技术就是Web API接口中Document的方法。

    当一个HTML文档切换到设计模式 designMode时,文档对象暴露 execCommand 方法,该方法允许运行命令来操纵可编辑区域的内容。大多数命令影响文档的选择(粗体,斜体等),而其他命令插入新元素(添加链接)或影响整行(缩进)。当使用contentEditable时,调用 execCommand() 将影响当前活动的可编辑元素。

    技术实现并不复杂,对于一个不懂得js的移动开发人员来说,看几天也能明白个大概,也可以上手调试及修改。
    我的建议是不要完全照搬,还是根据自己的需求,进行适当的改动。

    开发中遇到的坑

    1、使用UIWebView 还是 WKWebview?

    众所周知,wkwebview的性能要比前者高很多,我在开发的时候,也是首选它,但是在个别的js方法中,会遇到兼容性的问题。
    例如:插入的视频不能显示,插入的图片不能使用file:///来显示,只能通过转base64才可以,及其他。
    这些问题会给你带来很多的困扰,不止是显示,还有后续的缓存操作,导出HTML,删除操作等。
    为了更简单的开发,我选择了UIWebView,虽然牺牲一些性能,但是操作体验也是ok的,没有明显的差距。

    2、webview删除工具条

    通过分类的方法可以删除工具条,UIWebView和WKWebView都可以,具体可以参考文章:
    ios - 删除WebView键盘上的工具条

    3、中文输入法样式不改变的问题

    字体加粗:document.execCommand('bold', false, null)
    具体的问题是这样的:对字体“加粗”后,再次调用“加粗”,使用英文和数字是没有任何问题的,字体变成不加粗的状态;使用中文输入法时,没有确认之前,字体都是正常的,当选中确认的文字后,字体就会跟前面的样式走,还是加粗。
    这个问题不止是 加粗,斜体,下划线也是如此,可能是webview的一个bug,要解决这个问题,就需要在输入的前方增加一个'‌'字符。
    '‌':放在电子文本的两个字符之间,抑制本来会发生的连字,也就是不使用之前的样式。
    具体的用法如下:

    if (document.queryCommandState('bold')) {
            document.execCommand('bold', false, null);
            document.execCommand('insertHTML', false, '‌');
        } else {
            document.execCommand('bold', false, null);
        }
    

    以上的方式虽然可以解决富文本中兼容性的bug,但是逻辑写起来特别麻烦,而且还存在其他的漏洞,今天无意间又发现了一种新的解决方案。

    if (document.queryCommandState('bold')) {
            document.execCommand('bold', false, 'div');
        } else {
            document.execCommand('bold', false, null);
        }
    

    经过了一段时间的测试和开发,以上两种方式必须同时使用,才能解决webview中设置字体的bug

    4、换行光标跟随问题

    在 ZSSRichTextEditor 文件中,有一个方法:calculateEditorHeightWithCaretPosition 是通过计算文字的高度与当前偏移量做计算,然后进行滚动,达到跟随输入光标位置的现象,getCaretYPosition方法中,
    我增加一个normalize() 方法,解决了一些兼容性的问题。
    normalize() 方法移除空的文本节点,并连接相邻的文本节点。

    zss_editor.getCaretYPosition = function() {
        var sel = window.getSelection();
        // Next line is comented to prevent deselecting selection. It looks like work but if there are any issues will appear then uconmment it as well as code above.
        //sel.collapseToStart();
        var range = sel.getRangeAt(0);
        var span = document.createElement('span');// something happening here preventing selection of elements
        range.collapse(false);
        range.insertNode(span);
        var topPosition = span.offsetTop;
        var spanParent = span.parentNode;
        spanParent.removeChild(span);
        spanParent.normalize();
        return topPosition;
    }
    

    5、输入中文时,光标跳动问题

    在最后一行,换行到新的一行进行输入的时候,如果是汉字输入,会产生联想输入条,在还没有确定输入内容的时候,UIWebView是不知道你需要的高度的,这个时候,由于触发了selectionchange,会导致输入时候,整个界面不断的抖动,因此在webview的最后面,强制插入一个空白的div(footer),使得输入始终是在已有的区域范围内的,然后在键盘弹起和收回的时候,设置编辑内容和footer的高度。

            <!-- ZSSRichTextEditor Editable Content -->
        <div id="zss_editor_content" class="zs_editor_content"     contenteditable="true" placeholder="">
            <!-- insertHTML -->
            </div>
    
        <!-- Footer -->
        <div id="zss_editor_footer"></div>
    

    6、键盘自动唤起

    在进入编辑器时,调用js方法设置焦点,达到唤起键盘的目的,但是无论怎么调用,都是不管用。后来才发现UIWebView的一个属性,设置以后就ok了,但是弹起的效果不太好看,不知道为什么。

    self.keyboardDisplayRequiresUserAction = NO;
    

    Available in iOS 6.0 and later.默认是YES
    如果设置为YES,用户必须明确的点击页面上的元素或者相关联的输入页面来显示键盘;如果设置为NO,一个元素的焦点事件导致输入视图的显示和自动关联这个元素。

    演示图:

    222.gif

    参考文章:
    document.execCommand API文档
    HTML6种空格的区别 &nbsp;&ensp;&emsp;&thinsp;&zwnj;&zwj;
    利用contenteditable属性与execCommand()方法制作简易富文本编辑器
    iOS的webview下的一个bug
    基于 UIWebView 的富文本编辑器实践

    相关文章

      网友评论

      • jinlei_123:你好,请问楼主输入抖动是如何处理的呢? 为什么按照楼主上面的介绍做后,依然会抖动呢?
      • 3e137ed3a7e2:楼主,我现在使用这个demo,用document.execCommand('bold', false, null)给文字加粗第一次没有效果,第二次才有效果,取消也是一样,用了你上面的方法之后,取消加粗是没有问题了,加粗还是需要第二次加粗才有效果。但是如果这一行有多个效果,比如加粗,斜体,会取消所有的效果,加粗和斜体都没有了。希望楼主能帮忙,谢谢
      • 75ec5e185690:请问一下,调出字体设置界面时,怎么保持webview的焦点不丢失呢?
      • Andy_WangPeng:坐等demo
      • f593a1419078:烙铁,文字解决“3、中文输入法样式不改变的问题”的方案1跟我能收集到的资料相同,但是这样会导致一些问题
        1、”<strike>很高兴</strike>认识你“,当用户删除或者移动光标导致“兴”之后,理论上应该输入的文字应该属于strike标签内的,但是应该有一个空格,所以就还是之前的样式。
        我感觉最根本的原因还是插入了一个空格导致的
        2、删除到例子1中的“兴”之后需要多点击移除删除按钮去删除看不见的空格

        // 单纯的删除操作,可以检测到最后一个是插入的空格来手动删除它。但是移动光标这种就很坑了啊。目前想到的是做一个和文本框一样大小的隐藏 div 然后监听 div 的 click 事件,然后去获取当前光标的位置,去做类似于删除操作的逻辑。

        而且没有看懂博主的方案2啊,设置了那个'div'没有效果呢?
        楼主有没有遇到提到的这两个bug啊,怎么处理的。
        求分享
      • 小小志伟:你好,插入图片时候只能添加一次,请问你是怎么解决的
        小小志伟:@囧rg 嗯 ,好的👌。对图片上传成功或失败这个做了吗?
        囧rg:@小小志伟 找一个多选图片的组件,然后通过html的方式插入
        小小志伟:就是说怎么添加多张图片
      • 无畏009:最近也在做关于富文本编辑,转html标签,然后再供小程序使用,我看你的第二篇文章中讲述了关于tableView制作富文本编辑器,我对这块比较好奇,我自己是通过YYTextView来做的,目前还在尝试开发中,但是问题比较多,想请教下关于tableView来做的一些思路
        无畏009:今天尝试,碰到俩出问题:
        1、当第一次进去编辑页面的时候,第一个textView的默认高度是否是屏幕的高度,否则点击空白进入不了编辑状态,当然加手势可以,但是判断逻辑会增加。
        2、当在一段文字中间插入图片,是否把之前的文字拆分,如果拆分,当我把图片删除,怎么保证之前的图文还在同一个cell里面,是通过状态判断么?
        无畏009:方便加你的联系方式么?
        囧rg:@陈建蕾 什么问题,具体说下
      • 小小志伟:问下下边的toolbar的view是怎么做?是隐藏视图之后自定义,还是用self.addCustomToolbarItem(with: button)在原来基础上自定义。:smiley:
        小小志伟:@囧rg 好的 :+1:
        囧rg:1、先删除webview自带的toolbar
        2、添加一个自定义view(custool)
        3、根据键盘的高度,来设置custool的高度,并且改变webview的高度
      • 小小志伟:你好 ,问下怎么添加方形列表?
        囧rg:@小小志伟 不太清楚,一会都是调用,没有研究,你试试第三个参数
        小小志伟:@囧rg 我说的是document.execcommand执行命令里的这两种列表
        InsertOrderedList 切换当前选中区是编号列表还是常规格式化块。
        InsertUnorderedList 切换当前选中区是项目符号列表还是常规格式化块。
        还需要的是列表前面是方形,其他两种是圆点和数字的
        囧rg:@小小志伟 就是在controller上添加view,然后监听键盘事件,改变高度
      • Charims:大佬,求个demo啊
        囧rg:@Charims demo没有,如果开发遇到的问题,可以一起讨论
      • 剁椒鸡蛋zy:大佬 求demo
      • 杰克道长:求大佬 给个demo,目前急需用:pray: :pray: :pray: 在线等,挺急的:joy: :joy:
      • 地瓜馒头:用ZSSRichTextEditor的话,文字输入过多的情况(100字以上),再输入文字会卡顿,请问有没有遇到过。
        囧rg:没有遇到过
      • Civel_Xu:能不能 给个 demo
        囧rg:@Civel_Xu 目前没有整理
      • 彩虹丶直至黑白:我之前也在用ZSSRichTextEditor,感觉你这个更加简单易用,有没有demo给参考一下,大佬!
        xfx_itachi:@囧rg 有qq吗,我也是基于ZS去修改的,遇到了一些问题,想跟您交流一下
        彩虹丶直至黑白:@囧rg 好的大佬,整理出来应该不少人会用:smile:
        囧rg:现在集成到项目里面了,目前还没有整理出来。过一阵有时间整理下。

      本文标题:IOS - WebView富文本开发

      本文链接:https://www.haomeiwen.com/subject/uswxxftx.html