未读Android收藏集

Android富文本编辑器进阶版(干货,IOS可照搬逻辑)

2019-06-15  本文已影响0人  Rex_叶然

本文主要是讲解部分原理,源码及其使用请移步Github

https://github.com/RexSuper/RichEditor

演示apk下载​​​

演示apk下载

[https://github.com/RexSuper/RichEditor/blob/master/RichHtmlEditorforAndroid/app/release/RichEditorAndroid.apk]

Demo
https://github.com/RexSuper/RichEditor/tree/example/Example

Add it in your root build.gradle at the end of repositories:

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
Step 2. Add the dependency

    dependencies {
            implementation 'com.github.RexSuper:RichEditor:1.0.3'
    }
image.gif

github上的示例代码必须看,因为富文本有些功能后续不得不自己填充,比如用户的资源文件得先放到自己服务器生成链接等等

2019-08-20 更新日志 增加音频功能 增加插入文件下载功能 和视频下载功能
2019-08-16 更新日志 增加各种文件功能
2019-08-15 更新日志 增加添加视频功能

本文利用本地html实现了安卓端 所需要的各种复杂富文本并持续优化中

前言:

富文本显示还好,Android富文本编辑一直是一个大坑,还得考虑和其他端同步的问题,问题是你无论用什么方式实现,EditText支持的标签并不多,自定义span或者webview自定义标签也较为繁琐。

用html+webview+js肯定是最合适的可直接导出html兼容性高,Android端用js调用本地静态网页中的contenteditable(此原理做IOS富文本编辑可以无缝照搬)

本文致力于网络常见能搜到的功能实现原理外,补全其他可能遇到的坑,网上能搜到的内容只提关键字

本文也是基础RichEditor for Android思路上一个优化和讲解。它提供了如何和html edit之间交流。理论上来说html能实现的安卓就能实现了,我们只是需要找到这些我们需要的方法


简单版图例

image
image
image
---> 支持功能 Support function <---
Video Image Audio Files and Download
Blod Italic Subscript Strikethrough
Underline JustifyLeft JustifyCenter JustifyRight
Blockquote Heading Undo Redo
Indent Outdent InsertLink Checkbox
TextColor TextBackgroundColor FontSize UnorderedList
OrderedList Hint InsertLink Superscript

基本原理:最小模型示例

  1. 编辑器的框架搭建(以加粗为例,其他居中 撤销什么的 均是一个逻辑 事件监听 html自带)最小实现模型

asset里面放置一些静态网页和我们需要的初始化css

image image.gif

editor.html

一个简单的带 contenteditable="true"的内容

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="user-scalable=no">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link rel="stylesheet" type="text/css" href="normalize.css">
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="editor" contenteditable="true"></div>
<script type="text/javascript" src="rich_editor.js"></script>
</body>
</html>

image.gif

安卓通过js和html互相调用 例如设置加粗

rich_editor.js

RE.editor = document.getElementById('editor');

RE.setBold = function() {
    document.execCommand('bold', false, null);
}
image.gif

Webview中调用js中的加粗

//简化最小模型代码

public void setBold() {
    exec("javascript:RE.setBold();");
}

public void exec(String trigger) {
    load(trigger)
}

private void load(String trigger) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      evaluateJavascript(trigger, null);
    } else {
      loadUrl(trigger);
    }
}
image.gif

1.网页的contenteditable如何实现hint功能

方法1:

editor.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>

.placeholder::after  {
    content: attr(placeholder);
    position: absolute;
    top: 10px;
    color: #a9a9a9;
}
.placeholder-hide::after {
    display:none;
}
</style>
</head>
<body>
<div class="editor placeholder" contenteditable="true" placeholder="你想说什么"></div>
<script>

 document.querySelector('.editor').addEventListener("input", function(event) {
    var inputValue = event.target.innerHTML;
    if (inputValue) {
    document.querySelector('.editor').className = 'editor placeholder placeholder-hide'
    } else {
    document.querySelector('.editor').className = 'editor placeholder'
    }
 })

</script>

</body>
</html>

image.gif

方法2

js

RE.setPlaceholder = function(placeholder) {
    RE.editor.setAttribute("placeholder", placeholder);
}

css

#editor[placeholder]:empty:not(:focus):before {
  content: attr(placeholder);
  color: #9B9B9B;
  font-size:15px;
}}
image.gif

抽取成设置方法

<script>
function setPlaceholderColor (color) {
  var placeHolderStyle = document.querySelector("#placeholder-style");
  var styleContent = "#editor:empty:not(:focus):before {color:" + color +"}";
  if (placeHolderStyle) {
    placeHolderStyle.innerText = styleContent
  } else {
    placeHolderStyle = document.createElement('style')
    placeHolderStyle.setAttribute('id', 'placeholder-style')
    placeHolderStyle.innerText = styleContent
    document.documentElement.appendChild(placeHolderStyle)
  }
}
</script>
image.gif
  public void setPlaceholderColor(String color) {
        exec("javascript:RE.setPlaceholderColor('" + color+ "');");
  }
image.gif

2.如何获取光标所在文字的所有style(需求场景 如选中了加粗 B变色,但你光标选中了)

rich_editor.js

配合7:addEventListener

RE.getSelectedNode = function() {
    var node,selection;
    if (window.getSelection) {
        selection = getSelection();
        node = selection.anchorNode;
    }
    if (!node && document.selection) {
        selection = document.selection
        var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
        node = range.commonAncestorContainer ? range.commonAncestorContainer :
        range.parentElement ? range.parentElement() : range.item(0);
    }
    if (node) {
        var item =  (node.nodeName == "#text" ? node.parentNode : node);

         console.log("innerHTML:"+item.innerHTML);
         console.log("font-size:"+item.style["font-size"]);
         console.log("color:"+item.getAttribute("color"));
         console.log("queryCommandState1 bold:"+document.queryCommandState('bold'));
    }
}
image.gif

4.如何自动换行

    public void setNewLine() {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.insertHTML('<br></br>');");
    }
image.gif

5.如何处理图片

5.1安卓实现webview图片点击放大方法回调

这种方式比网上搜出来PageFinish后要好

loadUrl("javascript:(function())有时候会因为加载问题,导致代码没添加进去,那种有bug
image.gif

现提供更好的方式,同时实现的

  public final static String IMG_CLICK_JS = "<script type='text/javascript'>window.onload = function(){" +
            "var $img = document.getElementsByTagName('img');" +
            "for(var p in  $img){" +
            "    if (typeof $img[p] === 'object') {" +
            "        $img[p].style.width = '100%';" +
            "        $img[p].style.height ='auto';" +
            "        $img[p].onclick = function(e){" +
            "            ImgClick(e.srcElement.src);" +
            "        };" +
            "    }" +
            "}" +
            "};" +
            "function ImgClick(src) {" +
            "    var message = {" +
            "        'imgUrl' : src," +
            "    };" +
            "   window.imageOnclick.openImage(src);" +
            "};" +
            "</script>";

image.gif

*你也可以按照7.webview和js交互 console.log()传值方式 替换window.imageOnclick.openImage(src);"

将上面代码 直接加入到你的html中

实现对应回调

        webview.getSettings().setJavaScriptEnabled(true);
        webview.addJavascriptInterface(new JavascriptInterfaceImageOnclick(), "imageOnclick");
image.gif
 private class JavascriptInterfaceImageOnclick {

        @android.webkit.JavascriptInterface
        public void openImage(String imgUrl) {
            if (mOnClickImageTagListener != null && !TextUtils.isEmpty(imgUrl)) {
                mOnClickImageTagListener.onClick(imgUrl);
            }
        }
    }
image.gif

6.自带只能实现固定几种的font size (1-7自带几种)怎么指定大小实现font-size

//待更新

font size 类似于

7.webview和js交互

addJavascriptInterface
removeJavascriptInterface
evaluateJavascript
image.gif

一般是addJavascriptInterface或者

shouldOverrideUrlLoading
image.gif

接收信息

其实最好用的是,也最安全

console.log()  webview接收

editor(WebView)-->webChromeClient -->onConsoleMessage
image.gif

8.如何在客户端load自带美化的css解决

1.不可二次编辑
loadDataWithBaseURL(String baseUrl, String data,
        String mimeType, String encoding, String historyUrl)

2.可二次编辑
 editor.loadCSS("file:///android_asset/article_night.css")

image.gif

无法继续编辑的问题

9.事件监听

RE.editor.addEventListener("input", RE.callback);//其他html支持的 keyup ,selectionchange都支持 选中 文本变化 可以查下资料
image.gif

源码下载

https://github.com/RexSuper/RichHtmlEditorForAndroid

一定要理解,不然产品随便有个新需求你将寸步难行

10.添加视频

//&nbsp; 让其可以继续进去编辑模式
RE.insertVideo = function(url,custom) {
    var html = '&nbsp;<video src="' + url + '" ' + custom +'></video>&nbsp;';
    RE.insertHTML(html);
}
image.gif
private void addVideo() {
        //需要编辑框有光标才行
        richEditor.focusEditor();
//        pb.setVisibility(View.VISIBLE);
        //将视频上传到自己服务器得到链接
        //============>
        richEditor.setNeedSetNewLineAfter(true);
        richEditor.insertVideo("https://www.w3school.com.cn/example/html5/mov_bbb.mp4",
                        //增加进度控制
                "controls=\"controls\"" +
                        //视频显示第一帧
                        " initial-time=\"0.01\" " +
                        //宽高
                        "height=\"300\" " +
                        //样式
                        " style=\"margin-top:10px;max-width:100%;\""
        );

    }
image.gif

特别鸣谢

思路参考 RichEditor for Android

前端知识修正:@ZX

结尾:

这是一个不该由客户端实现又可以实现的功能

上一篇 下一篇

猜你喜欢

热点阅读