美文网首页Android开发
Android富文本编辑器添加表情

Android富文本编辑器添加表情

作者: 你的益达233 | 来源:发表于2020-11-18 11:38 被阅读0次

    原来编辑器是没法输入表情的

    原来的rich_editor.js是下面这样的

    /**
     * Copyright (C) 2015 Wasabeef
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    var RE = {};
    
    RE.currentSelection = {
    "startContainer": 0,
    "startOffset": 0,
    "endContainer": 0,
    "endOffset": 0};
    
    RE.editor = document.getElementById('editor');
    
    document.addEventListener("selectionchange", function() { RE.backuprange(); });
    
    // Initializations
    RE.callback = function() {
       var ranges = [
     '\ud83c[\udf00-\udfff]',
     '\ud83d[\udc00-\ude4f]',
     '\ud83d[\ude80-\udeff]'
     ];
    
    var oldlen=RE.editor.innerHTML;
    var newlen=RE.editor.innerHTML.replace(new RegExp(ranges.join('|'), 'g'), '');
    
    if(oldlen!=newlen){
    RE.backuprange();
    RE.editor.innerHTML =  RE.editor.innerHTML.replace(new RegExp(ranges.join('|'), 'g'), '');
    RE.restorerange();
    }
    //RE.editor.focus();
    window.location.href = "re-callback://" + encodeURI(RE.getHtml());
    }
    
    RE.setHtml = function(contents) {
    RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
    }
    
    RE.getHtml = function() {
    
    var ranges = [
    '\ud83c[\udf00-\udfff]',
    '\ud83d[\udc00-\ude4f]',
    '\ud83d[\ude80-\udeff]'
    ];
    
    return RE.editor.innerHTML.replace(new RegExp(ranges.join('|'), 'g'), '');
    }
    
    RE.getText = function() {
    return RE.editor.innerText;
    }
    
    RE.setBaseTextColor = function(color) {
    RE.editor.style.color  = color;
    }
    
    RE.setBaseFontSize = function(size) {
    RE.editor.style.fontSize = size;
    }
    
    RE.setPadding = function(left, top, right, bottom) {
      RE.editor.style.paddingLeft = left;
      RE.editor.style.paddingTop = top;
      RE.editor.style.paddingRight = right;
      RE.editor.style.paddingBottom = bottom;
    }
    
    RE.setBackgroundColor = function(color) {
    document.body.style.backgroundColor = color;
    }
    
    RE.setBackgroundImage = function(image) {
    RE.editor.style.backgroundImage = image;
    }
    
    RE.setWidth = function(size) {
    RE.editor.style.minWidth = size;
    }
    
    RE.setHeight = function(size) {
    RE.editor.style.height = size;
    }
    
    RE.setTextAlign = function(align) {
    RE.editor.style.textAlign = align;
    }
    
    RE.setVerticalAlign = function(align) {
    RE.editor.style.verticalAlign = align;
    }
    
    RE.setPlaceholder = function(placeholder) {
    RE.editor.setAttribute("placeholder", placeholder);
    }
    
    RE.undo = function() {
    document.execCommand('undo', false, null);
    }
    
    RE.redo = function() {
    document.execCommand('redo', false, null);
    }
    
    RE.setBold = function() {
    document.execCommand('bold', false, null);
    }
    
    RE.setItalic = function() {
    document.execCommand('italic', false, null);
    }
    
    RE.setSubscript = function() {
    document.execCommand('subscript', false, null);
    }
    
    RE.setSuperscript = function() {
    document.execCommand('superscript', false, null);
    }
    
    RE.setStrikeThrough = function() {
    document.execCommand('strikeThrough', false, null);
    }
    
    RE.setUnderline = function() {
    document.execCommand('underline', false, null);
    }
    
    RE.setBullets = function() {
    document.execCommand('InsertUnorderedList', false, null);
    }
    RE.setBullets = function(b) {
    document.execCommand('InsertUnorderedList', false, b);
    //if(b){
    //document.execCommand('InsertUnorderedList', false, b);
    //}else{
    //document.execCommand('InsertUnorderedList', false, null);
    //}
    }
    RE.setNumbers = function() {
    document.execCommand('InsertOrderedList', false, null);
    }
    RE.setNumbers = function(b) {
    document.execCommand('InsertOrderedList', false, b);
    //if(b){
    //document.execCommand('InsertOrderedList', false, b);
    //  }else{
    //document.execCommand('InsertOrderedList', false, null);
    //  }
    }
    RE.setTextColor = function(color) {
    RE.restorerange();
    document.execCommand("styleWithCSS", null, true);
    document.execCommand('foreColor', false, color);
    document.execCommand("styleWithCSS", null, false);
    }
    
    RE.setTextBackgroundColor = function(color) {
    RE.restorerange();
    document.execCommand("styleWithCSS", null, true);
    document.execCommand('hiliteColor', false, color);
    document.execCommand("styleWithCSS", null, false);
    }
    
    RE.setFontSize = function(fontSize){
    document.execCommand("fontSize", false, fontSize);
    }
    
    RE.setHeading = function(heading,b) {
    if(b)
    document.execCommand('formatBlock', false, '<h'+heading+'>');
    else
    document.execCommand('formatBlock', false, '<p>');
    }
    
    RE.setIndent = function() {
    document.execCommand('indent', false, null);
    }
    
    RE.setOutdent = function() {
    document.execCommand('outdent', false, null);
    }
    
    RE.setJustifyLeft = function() {
    document.execCommand('justifyLeft', false, null);
    }
    
    RE.setJustifyCenter = function() {
    document.execCommand('justifyCenter', false, null);
    }
    
    RE.setJustifyRight = function() {
    document.execCommand('justifyRight', false, null);
    }
    
    RE.setBlockquote = function(b) {
    if(b)
    document.execCommand('formatBlock', false, '<blockquote>');
    else
    document.execCommand('formatBlock', false, '<p>');
    }
    
    //插入图片
    RE.insertImage = function(url, alt) {
    //var html = '<img  src="' + url + '" alt="' + alt + '" /><p align=center style="color:#aaaaaa">来自陌筹君App的图片</p><hr align=center width=200 color=#aaaaaa size=1 /><br/><br/>';
    var html = '<img  src="' + url + '" /><br/><br/>';
    RE.insertHTML(html);
    }
    
    //插入分割线
    RE.insertHr = function() {
    var html = '<hr color=#e2e2e2 size=1 /><br/>';
    RE.insertHTML(html);
    }
    
    RE.insertHTML = function(html) {
    RE.restorerange();
    document.execCommand('insertHTML', false, html);
    }
    
    RE.insertLink = function(url, title) {
    RE.restorerange();
    var sel = document.getSelection();
    if (sel.toString().length == 0) {
    document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
    } else if (sel.rangeCount) {
       var el = document.createElement("a");
       el.setAttribute("href", url);
       el.setAttribute("title", title);
    
       var range = sel.getRangeAt(0).cloneRange();
       range.surroundContents(el);
       sel.removeAllRanges();
       sel.addRange(range);
       }
    RE.callback();
    }
    
    RE.setTodo = function(text) {
    var html = '<input type="checkbox" name="'+ text +'" value="'+ text +'"/> &nbsp;';
    document.execCommand('insertHTML', false, html);
    }
    
    RE.prepareInsert = function() {
    RE.backuprange();
    }
    
    RE.backuprange = function(){
    var selection = window.getSelection();
    if (selection.rangeCount > 0) {
      var range = selection.getRangeAt(0);
      RE.currentSelection = {
      "startContainer": range.startContainer,
      "startOffset": range.startOffset,
      "endContainer": range.endContainer,
      "endOffset": range.endOffset};
    }
    }
    
    RE.restorerange = function(){
    var selection = window.getSelection();
    selection.removeAllRanges();
    var range = document.createRange();
    range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
    range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
    selection.addRange(range);
    }
    
    RE.enabledEditingItems = function(e) {
    var items = [];
    
    if (document.queryCommandState('bold')) {
    items.push('bold');
    }
    if (document.queryCommandState('italic')) {
    items.push('italic');
    }
    if (document.queryCommandState('subscript')) {
    items.push('subscript');
    }
    if (document.queryCommandState('superscript')) {
    items.push('superscript');
    }
    if (document.queryCommandState('strikeThrough')) {
    items.push('strikeThrough');
    }
    if (document.queryCommandState('underline')) {
    items.push('underline');
    }
    if (document.queryCommandState('insertOrderedList')) {
    items.push('orderedList');
    }
    if (document.queryCommandState('insertUnorderedList')) {
    items.push('unorderedList');
    }
    if (document.queryCommandState('justifyCenter')) {
    items.push('justifyCenter');
    }
    if (document.queryCommandState('justifyFull')) {
    items.push('justifyFull');
    }
    if (document.queryCommandState('justifyLeft')) {
    items.push('justifyLeft');
    }
    if (document.queryCommandState('justifyRight')) {
    items.push('justifyRight');
    }
    if (document.queryCommandState('insertHorizontalRule')) {
    items.push('horizontalRule');
    }
    var formatBlock = document.queryCommandValue('formatBlock');
    if (formatBlock.length > 0) {
    items.push(formatBlock);
    }
    
    if(e.which==13){
    items.push("enter");
    }
    
    
    var ranges = [
    '\ud83c[\udf00-\udfff]',
    '\ud83d[\udc00-\ude4f]',
    '\ud83d[\ude80-\udeff]'
    ];
    
    window.location.href = "re-state://" + encodeURI(items.join(','))+"@_@"+encodeURI(RE.getHtml());
    }
    
    RE.focus = function() {
    var range = document.createRange();
    range.selectNodeContents(RE.editor);
    range.collapse(false);
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
    RE.editor.focus();
    }
    
    RE.blurFocus = function() {
    RE.editor.blur();
    }
    
    RE.removeFormat = function() {
    execCommand('removeFormat', false, null);
    }
    
    // Event Listeners
    RE.editor.addEventListener("input", RE.callback);
    RE.editor.addEventListener("keyup", function(e) {
    //RE.enabledEditingItems(e);
       var KEY_LEFT = 37, KEY_RIGHT = 39;
       if (e.which == KEY_LEFT || e.which == KEY_RIGHT || e.which ==8 || e.which == 13) {
       RE.enabledEditingItems(e);
       }
    });
    RE.editor.addEventListener("click", RE.enabledEditingItems);
    

    主要是

    var ranges = [
         '\ud83c[\udf00-\udfff]',
         '\ud83d[\udc00-\ude4f]',
         '\ud83d[\ude80-\udeff]'
     ];
    

    这样的代码是表情的,它全都替换为空格了
    好处:****本来WebView直接显示表情是有问题的,所以它适用于不需要表情的需求,也是不错的

    修改rich_editor.js文件

    /**
     * Copyright (C) 2015 Wasabeef
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    var RE = {};
    
    RE.currentSelection = {
    "startContainer": 0,
    "startOffset": 0,
    "endContainer": 0,
    "endOffset": 0};
    
    RE.editor = document.getElementById('editor');
    
    document.addEventListener("selectionchange", function() { RE.backuprange(); });
    
    // Initializations
    RE.callback = function() {
    //   var ranges = [
    // '\ud83c[\udf00-\udfff]',
    // '\ud83d[\udc00-\ude4f]',
    // '\ud83d[\ude80-\udeff]'
    // ];
    //
    //var oldlen=RE.editor.innerHTML;
    ////var newlen=RE.editor.innerHTML.replace(new RegExp(ranges.join('|'), 'g'), '');
    //
    //if(oldlen!=newlen){
    //RE.backuprange();
    ////RE.editor.innerHTML =  RE.editor.innerHTML.replace(new RegExp(ranges.join('|'), 'g'), '');
    //RE.restorerange();
    //}
    //RE.editor.focus();
    window.location.href = "re-callback://" + encodeURI(RE.getHtml());
    }
    
    RE.setHtml = function(contents) {
    RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
    }
    
    RE.getHtml = function() {
    
    //var ranges = [
    //'\ud83c[\udf00-\udfff]',
    //'\ud83d[\udc00-\ude4f]',
    //'\ud83d[\ude80-\udeff]'
    //];
    
    return RE.editor.innerHTML;
    }
    
    RE.getText = function() {
    return RE.editor.innerText;
    }
    
    RE.setBaseTextColor = function(color) {
    RE.editor.style.color  = color;
    }
    
    RE.setBaseFontSize = function(size) {
    RE.editor.style.fontSize = size;
    }
    
    RE.setPadding = function(left, top, right, bottom) {
      RE.editor.style.paddingLeft = left;
      RE.editor.style.paddingTop = top;
      RE.editor.style.paddingRight = right;
      RE.editor.style.paddingBottom = bottom;
    }
    
    RE.setBackgroundColor = function(color) {
    document.body.style.backgroundColor = color;
    }
    
    RE.setBackgroundImage = function(image) {
    RE.editor.style.backgroundImage = image;
    }
    
    RE.setWidth = function(size) {
    RE.editor.style.minWidth = size;
    }
    
    RE.setHeight = function(size) {
    RE.editor.style.height = size;
    }
    
    RE.setTextAlign = function(align) {
    RE.editor.style.textAlign = align;
    }
    
    RE.setVerticalAlign = function(align) {
    RE.editor.style.verticalAlign = align;
    }
    
    RE.setPlaceholder = function(placeholder) {
    RE.editor.setAttribute("placeholder", placeholder);
    }
    
    RE.undo = function() {
    document.execCommand('undo', false, null);
    }
    
    RE.redo = function() {
    document.execCommand('redo', false, null);
    }
    
    RE.setBold = function() {
    document.execCommand('bold', false, null);
    }
    
    RE.setItalic = function() {
    document.execCommand('italic', false, null);
    }
    
    RE.setSubscript = function() {
    document.execCommand('subscript', false, null);
    }
    
    RE.setSuperscript = function() {
    document.execCommand('superscript', false, null);
    }
    
    RE.setStrikeThrough = function() {
    document.execCommand('strikeThrough', false, null);
    }
    
    RE.setUnderline = function() {
    document.execCommand('underline', false, null);
    }
    
    RE.setBullets = function() {
    document.execCommand('InsertUnorderedList', false, null);
    }
    RE.setBullets = function(b) {
    document.execCommand('InsertUnorderedList', false, b);
    //if(b){
    //document.execCommand('InsertUnorderedList', false, b);
    //}else{
    //document.execCommand('InsertUnorderedList', false, null);
    //}
    }
    RE.setNumbers = function() {
    document.execCommand('InsertOrderedList', false, null);
    }
    RE.setNumbers = function(b) {
    document.execCommand('InsertOrderedList', false, b);
    //if(b){
    //document.execCommand('InsertOrderedList', false, b);
    //  }else{
    //document.execCommand('InsertOrderedList', false, null);
    //  }
    }
    RE.setTextColor = function(color) {
    RE.restorerange();
    document.execCommand("styleWithCSS", null, true);
    document.execCommand('foreColor', false, color);
    document.execCommand("styleWithCSS", null, false);
    }
    
    RE.setTextBackgroundColor = function(color) {
    RE.restorerange();
    document.execCommand("styleWithCSS", null, true);
    document.execCommand('hiliteColor', false, color);
    document.execCommand("styleWithCSS", null, false);
    }
    
    RE.setFontSize = function(fontSize){
    document.execCommand("fontSize", false, fontSize);
    }
    
    RE.setHeading = function(heading,b) {
    if(b)
    document.execCommand('formatBlock', false, '<h'+heading+'>');
    else
    document.execCommand('formatBlock', false, '<p>');
    }
    
    RE.setIndent = function() {
    document.execCommand('indent', false, null);
    }
    
    RE.setOutdent = function() {
    document.execCommand('outdent', false, null);
    }
    
    RE.setJustifyLeft = function() {
    document.execCommand('justifyLeft', false, null);
    }
    
    RE.setJustifyCenter = function() {
    document.execCommand('justifyCenter', false, null);
    }
    
    RE.setJustifyRight = function() {
    document.execCommand('justifyRight', false, null);
    }
    
    RE.setBlockquote = function(b) {
    if(b)
    document.execCommand('formatBlock', false, '<blockquote>');
    else
    document.execCommand('formatBlock', false, '<p>');
    }
    
    //插入图片
    RE.insertImage = function(url, alt) {
    //var html = '<img  src="' + url + '" alt="' + alt + '" /><p align=center style="color:#aaaaaa">来自陌筹君App的图片</p><hr align=center width=200 color=#aaaaaa size=1 /><br/><br/>';
    var html = '<img  src="' + url + '" /><br/><br/>';
    RE.insertHTML(html);
    //var html = '<img src="' + url + '" alt="' + alt + '" />';
    //RE.insertHTML(html);
    }
    
    //插入分割线
    RE.insertHr = function() {
    var html = '<hr color=#e2e2e2 size=1 /><br/>';
    RE.insertHTML(html);
    }
    
    RE.insertHTML = function(html) {
    RE.restorerange();
    document.execCommand('insertHTML', false, html);
    }
    
    RE.insertLink = function(url, title) {
    RE.restorerange();
    var sel = document.getSelection();
    if (sel.toString().length == 0) {
    document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
    } else if (sel.rangeCount) {
       var el = document.createElement("a");
       el.setAttribute("href", url);
       el.setAttribute("title", title);
    
       var range = sel.getRangeAt(0).cloneRange();
       range.surroundContents(el);
       sel.removeAllRanges();
       sel.addRange(range);
       }
    RE.callback();
    }
    
    RE.setTodo = function(text) {
    var html = '<input type="checkbox" name="'+ text +'" value="'+ text +'"/> &nbsp;';
    document.execCommand('insertHTML', false, html);
    }
    
    RE.prepareInsert = function() {
    RE.backuprange();
    }
    
    RE.backuprange = function(){
    var selection = window.getSelection();
    if (selection.rangeCount > 0) {
      var range = selection.getRangeAt(0);
      RE.currentSelection = {
      "startContainer": range.startContainer,
      "startOffset": range.startOffset,
      "endContainer": range.endContainer,
      "endOffset": range.endOffset};
    }
    }
    
    RE.restorerange = function(){
    var selection = window.getSelection();
    selection.removeAllRanges();
    var range = document.createRange();
    range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
    range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
    selection.addRange(range);
    }
    
    RE.enabledEditingItems = function(e) {
    var items = [];
    
    if (document.queryCommandState('bold')) {
    items.push('bold');
    }
    if (document.queryCommandState('italic')) {
    items.push('italic');
    }
    if (document.queryCommandState('subscript')) {
    items.push('subscript');
    }
    if (document.queryCommandState('superscript')) {
    items.push('superscript');
    }
    if (document.queryCommandState('strikeThrough')) {
    items.push('strikeThrough');
    }
    if (document.queryCommandState('underline')) {
    items.push('underline');
    }
    if (document.queryCommandState('insertOrderedList')) {
    items.push('orderedList');
    }
    if (document.queryCommandState('insertUnorderedList')) {
    items.push('unorderedList');
    }
    if (document.queryCommandState('justifyCenter')) {
    items.push('justifyCenter');
    }
    if (document.queryCommandState('justifyFull')) {
    items.push('justifyFull');
    }
    if (document.queryCommandState('justifyLeft')) {
    items.push('justifyLeft');
    }
    if (document.queryCommandState('justifyRight')) {
    items.push('justifyRight');
    }
    if (document.queryCommandState('insertHorizontalRule')) {
    items.push('horizontalRule');
    }
    var formatBlock = document.queryCommandValue('formatBlock');
    if (formatBlock.length > 0) {
    items.push(formatBlock);
    }
    
    if(e.which==13){
    items.push("enter");
    }
    
    
    //var ranges = [
    //'\ud83c[\udf00-\udfff]',
    //'\ud83d[\udc00-\ude4f]',
    //'\ud83d[\ude80-\udeff]'
    //];
    
    //window.location.href = "re-state://" + encodeURI(items.join(','))+"@_@"+encodeURI(RE.getHtml());
    window.location.href = "re-state://" + encodeURI(items.join(','));
    }
    
    RE.focus = function() {
    var range = document.createRange();
    range.selectNodeContents(RE.editor);
    range.collapse(false);
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
    RE.editor.focus();
    }
    
    RE.blurFocus = function() {
    RE.editor.blur();
    }
    
    RE.removeFormat = function() {
    execCommand('removeFormat', false, null);
    }
    
    // Event Listeners
    RE.editor.addEventListener("input", RE.callback);
    RE.editor.addEventListener("keyup", function(e) {
    //RE.enabledEditingItems(e);
       var KEY_LEFT = 37, KEY_RIGHT = 39;
       if (e.which == KEY_LEFT || e.which == KEY_RIGHT || e.which ==8 || e.which == 13) {
       RE.enabledEditingItems(e);
       }
    });
    RE.editor.addEventListener("click", RE.enabledEditingItems);
    

    看到没,重点把表情的代码放出来
    注意:记得editor.html中的js改为你修改后的xx.js

    直接给ACRichEmojiEditor

    package com.xf.activity.view;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Bitmap;
    import android.graphics.drawable.Drawable;
    import android.os.Build;
    import android.text.TextUtils;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.Gravity;
    import android.webkit.WebChromeClient;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    
    
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Locale;
    
    
    
    public class ACRichEmojiEditor extends WebView {
    
    public enum Type {
        BOLD,
        ITALIC,
        SUBSCRIPT,
        SUPERSCRIPT,
        STRIKETHROUGH,
        UNDERLINE,
        BLOCKQUOTE,
        NUMBERS,
        BULLETS,
        H1,
        H2,
        H3,
        H4,
        H5,
        H6
    }
    
    public interface OnTextChangeListener {
    
        void onTextChange(String text);
    }
    
    public interface OnDecorationStateListener {
    
        void onStateChangeListener(String text, List<Type> types);
    }
    
    public interface AfterInitialLoadListener {
    
        void onAfterInitialLoad(boolean isReady);
    }
    
    private static final String SETUP_HTML = "file:///android_asset/editor3.html";
    private static final String CALLBACK_SCHEME = "re-callback://";
    private static final String STATE_SCHEME = "re-state://";
    private boolean isReady = false;
    private String mContents;
    private OnTextChangeListener mTextChangeListener;
    private OnDecorationStateListener mDecorationStateListener;
    private AfterInitialLoadListener mLoadListener;
    private OnScrollChangedCallback mOnScrollChangedCallback;
    
    public ACRichEmojiEditor(Context context) {
        this(context, null);
    }
    
    public ACRichEmojiEditor(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.webViewStyle);
    }
    
    @SuppressLint("SetJavaScriptEnabled")
    public ACRichEmojiEditor(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    
        setVerticalScrollBarEnabled(false);
        setHorizontalScrollBarEnabled(false);
        getSettings().setJavaScriptEnabled(true);
        setWebChromeClient(new WebChromeClient());
        setWebViewClient(createWebviewClient());
        loadUrl(SETUP_HTML);
    
        applyAttributes(context, attrs);
    }
    
    protected EditorWebViewClient createWebviewClient() {
        return new EditorWebViewClient();
    }
    
    public void setOnTextChangeListener(OnTextChangeListener listener) {
        mTextChangeListener = listener;
    }
    
    public void setOnDecorationChangeListener(OnDecorationStateListener listener) {
        mDecorationStateListener = listener;
    }
    
    public void setOnInitialLoadListener(AfterInitialLoadListener listener) {
        mLoadListener = listener;
    }
    
    private void callback(String text) {
        mContents = text.replaceFirst(CALLBACK_SCHEME, "");
        if (mTextChangeListener != null) {
            mTextChangeListener.onTextChange(mContents);
        }
        return;
    }
    
    
    /**
     * WebView的滚动事件
     *
     * @param l
     * @param t
     * @param oldl
     * @param oldt
     */
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
    
        if (mOnScrollChangedCallback != null) {
            mOnScrollChangedCallback.onScroll(l - oldl, t - oldt);
        }
    
    }
    
    public OnScrollChangedCallback getOnScrollChangedCallback() {
        return mOnScrollChangedCallback;
    }
    
    public void setOnScrollChangedCallback(
            final OnScrollChangedCallback onScrollChangedCallback) {
        mOnScrollChangedCallback = onScrollChangedCallback;
    }
    
    
    /**
     * Impliment in the activity/fragment/view that you want to listen to the webview
     */
    public interface OnScrollChangedCallback {
        void onScroll(int dx, int dy);
    }
    
    
    private void stateCheck(String text) {
    
        if (!text.contains("@_@")) {
            String state = text.replaceFirst(STATE_SCHEME, "").toUpperCase(Locale.ENGLISH);
            List<Type> types = new ArrayList<>();
            for (Type type : Type.values()) {
                if (TextUtils.indexOf(state, type.name()) != -1) {
                    types.add(type);
                }
            }
    
            if (mDecorationStateListener != null) {
                mDecorationStateListener.onStateChangeListener(state, types);
            }
            return;
        }
    
        String state = text.replaceFirst(STATE_SCHEME, "").split("@_@")[0].toUpperCase(Locale.ENGLISH);
        List<Type> types = new ArrayList<>();
        for (Type type : Type.values()) {
            if (TextUtils.indexOf(state, type.name()) != -1) {
                types.add(type);
            }
        }
    
        if (mDecorationStateListener != null) {
            mDecorationStateListener.onStateChangeListener(state, types);
        }
    
        if (text.replaceFirst(STATE_SCHEME, "").split("@_@").length > 1) {
            mContents = text.replaceFirst(STATE_SCHEME, "").split("@_@")[1];
            if (mTextChangeListener != null) {
                mTextChangeListener.onTextChange(mContents);
            }
        }
    }
    
    private void applyAttributes(Context context, AttributeSet attrs) {
        final int[] attrsArray = new int[]{
                android.R.attr.gravity
        };
        TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
    
        int gravity = ta.getInt(0, NO_ID);
        switch (gravity) {
            case Gravity.LEFT:
                exec("javascript:RE.setTextAlign(\"left\")");
                break;
            case Gravity.RIGHT:
                exec("javascript:RE.setTextAlign(\"right\")");
                break;
            case Gravity.TOP:
                exec("javascript:RE.setVerticalAlign(\"top\")");
                break;
            case Gravity.BOTTOM:
                exec("javascript:RE.setVerticalAlign(\"bottom\")");
                break;
            case Gravity.CENTER_VERTICAL:
                exec("javascript:RE.setVerticalAlign(\"middle\")");
                break;
            case Gravity.CENTER_HORIZONTAL:
                exec("javascript:RE.setTextAlign(\"center\")");
                break;
            case Gravity.CENTER:
                exec("javascript:RE.setVerticalAlign(\"middle\")");
                exec("javascript:RE.setTextAlign(\"center\")");
                break;
        }
    
        ta.recycle();
    }
    
    /**
     * setText
     *
     * @param contents
     */
    public void setHtml(String contents) {
        if (contents == null) {
            contents = "";
        }
        try {
            exec("javascript:RE.setHtml('" + URLEncoder.encode(contents, "UTF-8") + "');");
        } catch (UnsupportedEncodingException e) {
            // No handling
        }
        mContents = contents;
    }
    
    /**
     * getText
     *
     * @return
     */
    public String getHtml() {
        return mContents;
    }
    
    public void setEditorFontColor(int color) {
        String hex = convertHexColorString(color);
        exec("javascript:RE.setBaseTextColor('" + hex + "');");
    }
    
    public void setEditorFontSize(int px) {
        exec("javascript:RE.setBaseFontSize('" + px + "px');");
    }
    
    @Override
    public void setPadding(int left, int top, int right, int bottom) {
        super.setPadding(left, top, right, bottom);
        exec("javascript:RE.setPadding('" + left + "px', '" + top + "px', '" + right + "px', '" + bottom
                + "px');");
    }
    
    @Override
    public void setPaddingRelative(int start, int top, int end, int bottom) {
        // still not support RTL.
        setPadding(start, top, end, bottom);
    }
    
    public void setEditorBackgroundColor(int color) {
        setBackgroundColor(color);
    }
    
    @Override
    public void setBackgroundColor(int color) {
        super.setBackgroundColor(color);
    }
    
    @Override
    public void setBackgroundResource(int resid) {
        Bitmap bitmap = ACRichUtils.decodeResource(getContext(), resid);
        String base64 = ACRichUtils.toBase64(bitmap);
        bitmap.recycle();
    
        exec("javascript:RE.setBackgroundImage('url(data:image/png;base64," + base64 + ")');");
    }
    
    @Override
    public void setBackground(Drawable background) {
        Bitmap bitmap = ACRichUtils.toBitmap(background);
        String base64 = ACRichUtils.toBase64(bitmap);
        bitmap.recycle();
    
        exec("javascript:RE.setBackgroundImage('url(data:image/png;base64," + base64 + ")');");
    }
    
    public void setBackground(String url) {
        exec("javascript:RE.setBackgroundImage('url(" + url + ")');");
    }
    
    public void setEditorWidth(int px) {
        exec("javascript:RE.setWidth('" + px + "px');");
    }
    
    public void setEditorHeight(int px) {
        exec("javascript:RE.setHeight('" + px + "px');");
    }
    
    public void setPlaceholder(String placeholder) {
        exec("javascript:RE.setPlaceholder('" + placeholder + "');");
    }
    
    public void loadCSS(String cssFile) {
        String jsCSSImport = "(function() {" +
                "    var head  = document.getElementsByTagName(\"head\")[0];" +
                "    var link  = document.createElement(\"link\");" +
                "    link.rel  = \"stylesheet\";" +
                "    link.type = \"text/css\";" +
                "    link.href = \"" + cssFile + "\";" +
                "    link.media = \"all\";" +
                "    head.appendChild(link);" +
                "}) ();";
        exec("javascript:" + jsCSSImport + "");
    }
    public  void setWebImageClick(WebView view) {
        String jsCode="javascript:(function(){" +
                "var imgs=document.getElementsByTagName(\"img\");" +
                " var array=new Array(); " +
                " for(var j=0;j<imgs.length;j++){ array[j]=imgs[j].src; }"+
                "for(var i=0;i<imgs.length;i++){" +
    
                "imgs[i].onclick=function(){" +
                "window.jsCallJavaObj.openImage(this.src,array);" +
                "}}})()";
        view.loadUrl(jsCode);
    }
    public  void setWebImageClick() {
        String jsCode="javascript:(function(){" +
                "var imgs=document.getElementsByTagName(\"img\");" +
                " var array=new Array(); " +
                " for(var j=0;j<imgs.length;j++){ array[j]=imgs[j].src; }"+
                "for(var i=0;i<imgs.length;i++){" +
    
                "imgs[i].onclick=function(){" +
                "window.jsCallJavaObj.openImage(this.src,array);" +
                "}}})()";
        exec("javascript:" + jsCode + "");
    }
    public void undo() {
        exec("javascript:RE.undo();");
    }
    
    public void redo() {
        exec("javascript:RE.redo();");
    }
    
    public void setBold() {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.setBold();");
    }
    
    public void setItalic() {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.setItalic();");
    }
    
    public void setSubscript() {
        exec("javascript:RE.setSubscript();");
    }
    
    public void setSuperscript() {
        exec("javascript:RE.setSuperscript();");
    }
    
    public void setStrikeThrough() {
        exec("javascript:RE.setStrikeThrough();");
    }
    
    public void setUnderline() {
        exec("javascript:RE.setUnderline();");
    }
    
    public void setTextColor(int color) {
        exec("javascript:RE.prepareInsert();");
    
        String hex = convertHexColorString(color);
        exec("javascript:RE.setTextColor('" + hex + "');");
    }
    
    public void setTextBackgroundColor(int color) {
        exec("javascript:RE.prepareInsert();");
    
        String hex = convertHexColorString(color);
        exec("javascript:RE.setTextBackgroundColor('" + hex + "');");
    }
    
    public void setFontSize(int fontSize) {
        if (fontSize > 7 || fontSize < 1) {
            Log.e("RichEditor", "Font size should have a value between 1-7");
        }
        exec("javascript:RE.setFontSize('" + fontSize + "');");
    }
    
    public void removeFormat() {
        exec("javascript:RE.removeFormat();");
    }
    
    public void setHeading(int heading, boolean b, boolean isItalic, boolean isBold, boolean isStrikeThrough) {
        exec("javascript:RE.prepareInsert();");
    
        exec("javascript:RE.setHeading('" + heading + "'," + b + ");");
    }
    
    public void setIndent() {
        exec("javascript:RE.setIndent();");
    }
    
    public void setOutdent() {
        exec("javascript:RE.setOutdent();");
    }
    
    public void setAlignLeft() {
        exec("javascript:RE.setJustifyLeft();");
    }
    
    public void setAlignCenter() {
        exec("javascript:RE.setJustifyCenter();");
    }
    
    public void setAlignRight() {
        exec("javascript:RE.setJustifyRight();");
    }
    
    public void setBlockquote(boolean b, boolean isItalic, boolean isBold, boolean isStrikeThrough) {
        exec("javascript:RE.prepareInsert();");
    
        exec("javascript:RE.setBlockquote(" + b + ");");
    }
    
    //设置点点
    public void setBullets() {
        exec("javascript:RE.setBullets();");
    }
    //设置点点
    public void setBullets(boolean b) {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.setBullets(" + b + ");");
        //Log.d("Acheng",b+":Bullets");
    }
    //设置数字
    public void setNumbers() {
        exec("javascript:RE.setNumbers();");
    }
    //设置数字
    public void setNumbers(boolean b) {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.setNumbers(" + b + ");");
        //Log.d("Acheng",b+":Numbers");
    }
    
    public void insertImage(String url, String alt) {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.insertImage('" + url + "', '" + alt + "');");
    }
    
    public void insertHr() {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.insertHr();");
    }
    
    
    public void insertLink(String href, String title) {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.insertLink('" + href + "', '" + title + "');");
    }
    
    public void insertTodo() {
        exec("javascript:RE.prepareInsert();");
        exec("javascript:RE.setTodo('" + ACRichUtils.getCurrentTime() + "');");
    }
    
    public void focusEditor() {
        requestFocus();
        exec("javascript:RE.focus();");
    }
    
    public void clearFocusEditor() {
        exec("javascript:RE.blurFocus();");
    }
    
    private String convertHexColorString(int color) {
        return String.format("#%06X", (0xFFFFFF & color));
    }
    
    protected void exec(final String trigger) {
        if (isReady) {
            load(trigger);
        } else {
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    exec(trigger);
                }
            }, 100);
        }
    }
    
    private void load(String trigger) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            evaluateJavascript(trigger, null);
        } else {
            loadUrl(trigger);
        }
    }
    
    protected class EditorWebViewClient extends WebViewClient {
        @Override
        public void onPageFinished(WebView view, String url) {
            isReady = url.equalsIgnoreCase(SETUP_HTML);
            if (mLoadListener != null) {
                mLoadListener.onAfterInitialLoad(isReady);
            }
        }
    
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            String decode;
            try {
                decode = URLDecoder.decode(url, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                // No handling
                return false;
            }
    
            if (TextUtils.indexOf(url, CALLBACK_SCHEME) == 0) {
                callback(decode);
                return true;
            } else if (TextUtils.indexOf(url, STATE_SCHEME) == 0) {
                stateCheck(decode);
                return true;
            }
    
            return super.shouldOverrideUrlLoading(view, url);
        }
    }
    }
    

    至此准备操作就好了

    使用

    要WebView显示是需要编码的
    思路:叫了接口配合下。app先编码content传给接口,接口解码做它的处理,处理完再编码传给app。app显示解码即可
    编码:

    URLEncoder.encode(content, "utf-8").replace("+"," ")  
    

    解码:

    wbView?.html = URLDecoderUtil.decode(data.data.content)
    

    ios和Android都用这种编码方式即可

    有问题请私信或者评论

    相关文章

      网友评论

        本文标题:Android富文本编辑器添加表情

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