【Android】基于webView打造富文本编辑器(H5)

作者 : admin 本文共21290个字,预计阅读时间需要54分钟 发布时间: 2024-06-17 共1人阅读

目录

  • 前言
  • 一、实现效果
  • 二、具体实现
    • 1. 导入网页资源
    • 2. 页面设计
    • 3. 功能调用
    • 4. 完整代码
  • 总结

前言

HTML5是构建Web内容的一种语言描述方式。HTML5是Web中核心语言HTML的规范,用户使用任何手段进行网页浏览时看到的内容原本都是HTML格式的,在浏览器中通过一些技术处理将其转换成为了可识别的信息。

而WebView 是一种嵌入式浏览器,原生APP应用可以用它来展示网络内容。其功能强大,除了具有一般View的属性和设置外,还可以对url请求、页面加载、渲染、页面交互进行强大的处理.。
【Android】基于webView打造富文本编辑器(H5)插图
所以,因为H5的跨平台和成本低的优势,越来越多的项目都使用了Android原生控件与WebView进行混合开发,用WebView加载html界面,实现本地安卓代码与HTML+CSS+JS的交互。

webView的基本使用可以参考这篇文章:https://blog.csdn.net/carson_ho/article/details/52693322

本文将利用webView实现一个富文本编辑器,它是一种可内嵌于浏览器,所见即所得的文本编辑器,其实质就是html代码,可改变文本样式、文间插入图片或视频等。我为了实现这一功能借鉴很多项目(主要是MRichEditor和RichEditTextCopyToutiao,都是基于 richeditor-android),修复了一些Bug,最终效果还行。借鉴的第三方库可移步我之前写的文章:常用的第三方开源库汇总


一、实现效果

【Android】基于webView打造富文本编辑器(H5)插图(1)

【Android】基于webView打造富文本编辑器(H5)插图(2)

二、具体实现

富文本编辑器主要功能就是文字大小、颜色、加粗、斜体、下划线、删除线、缩进、居中或靠左靠右,无序或有序列表,插入链接、图片、视频等。原有项目会存在一些导入html标签和输入框光标的bug,解决这些需要一点HTML+CSS+JS的知识。

1. 导入网页资源

在项目根目录下新建assets文件夹
【Android】基于webView打造富文本编辑器(H5)插图(3)
导入资源:对于熟悉网页端的开发人员来说,修改这些并不难。
【Android】基于webView打造富文本编辑器(H5)插图(4)

2. 页面设计

编辑器的一个按钮即对应着js中的一个函数,通过RichEditor自定义 view去调用js函数, 它继承自 Webview ,加载html文件,枚举类型Type定义了支持的排版格式。

public class RichEditor extends WebView {

	private static final String SETUP_HTML = "file:///android_asset/editor.html";
    public enum Type {
        BOLD,
        ITALIC,
        SUBSCRIPT,
        SUPERSCRIPT,
        STRIKETHROUGH,
        UNDERLINE,
        H1,
        H2,
        H3,
        H4,
        H5,
        H6,
        ORDEREDLIST,
        UNORDEREDLIST,
        JUSTIFYCENTER,
        JUSTIFYFULL,
        JUSTIFYLEFT,
        JUSTIFYRIGHT
    }
    @SuppressLint("SetJavaScriptEnabled")
    public RichEditor(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);
    }
}

其中​editor.html​即编辑器所展示的主页面

<!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>

RichEditor控件中的函数对应着​rich_editor.js​中的接口

RichEditor:

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

​rich_editor.js:

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

在布局中使用:

<com.text.richeditor.editor.RichEditor
        android:id="@+id/rich_Editor"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:overScrollMode="never" />

主要样式如下:
【Android】基于webView打造富文本编辑器(H5)插图(5)
除了底部的功能栏可以使用,最左边还有一个排版按钮,这里主要是为了不方便弹出底部时,可以选择使用弹窗弹出功能栏,功能是一致的,可以选择性阉割。使用某一功能时会有颜色高亮提示。

3. 功能调用

首先要在activity中初始化控件,实现setOnDecorationChangeListener接口,监听点击某个功能按钮时显示对应高亮,让用户看到现在正在所使用的排版格式。

		//输入框显示字体的大小
rich_Editor.setEditorFontSize(16)
//输入框显示字体的颜色
rich_Editor.setEditorFontColor(ContextCompat.getColor(this,R.color.deepGrey))
//输入框背景设置
rich_Editor.setEditorBackgroundColor(Color.WHITE)
//输入框文本padding
rich_Editor.setPadding(10, 10, 10, 10)
//输入提示文本
rich_Editor.setPlaceholder("点击输入正文!~")
rich_Editor.setOnDecorationChangeListener { _, types ->
val flagArr = ArrayList<String>()
for (i in types.indices) {
flagArr.add(types[i].name)
}
if (flagArr.contains("BOLD")) {
button_bold.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.BOLD, true)
} else {
button_bold.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.BOLD, false)
}
if (flagArr.contains("ITALIC")) {
button_italic.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.ITALIC, true)
} else {
button_italic.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ITALIC, false)
}
if (flagArr.contains("STRIKETHROUGH")) {
button_strikethrough.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.STRIKETHROUGH, true)
} else {
button_strikethrough.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.STRIKETHROUGH, false)
}
if (flagArr.contains("JUSTIFYCENTER")) {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, true)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, false)
} else {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, false)
}
if (flagArr.contains("JUSTIFYLEFT")) {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, true)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, false)
} else {
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, false)
}
if (flagArr.contains("JUSTIFYRIGHT")) {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, true)
} else {
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, false)
}
if (flagArr.contains("UNDERLINE")) {
button_underline.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.UNDERLINE, true)
} else {
button_underline.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.UNDERLINE, false)
}
if (flagArr.contains("ORDEREDLIST")) {
button_list_ol.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_list_ul.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ORDERED, true)
mEditorMenuFragment.updateActionStates(ActionType.UNORDERED, false)
} else {
button_list_ol.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ORDERED, false)
}
if (flagArr.contains("UNORDEREDLIST")) {
button_list_ul.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_list_ol.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ORDERED, false)
mEditorMenuFragment.updateActionStates(ActionType.UNORDERED, true)
} else {
button_list_ul.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.UNORDERED, false)
}
}

插入图片和视频:原本是调用特有的方法实现,但是可定制化不高,我就改成了插入html的形式

public void insertVideoPercentage(String url, String width, String height) {
exec("javascript:RE.prepareInsert();");
//        exec("javascript:RE.insertVideoWH('" + url + "', '" + width + "', '" + height + "');");
String testStr = "<video src=\"" + url + "\" width=\""+ width +"\"  height=\""+ height +"\" controls>
"
; exec("javascript:RE.insertHTML('" + testStr + "');"); } public void insertImage(String url, String alt) { exec("javascript:RE.prepareInsert();"); String testStr = "【Android】基于webView打造富文本编辑器(H5)插图(6)

	KeyboardUtils.registerSoftInputChangedListener(this) { height: Int ->
//键盘打开
isKeyboardShowing = height > 0
if (height > 0) {
//fl_action.visibility = View.GONE
val params = fl_action.layoutParams
params.height = height/2
fl_action.layoutParams = params
} else{
//if (fl_action.visibility != View.VISIBLE)
fl_action.visibility = View.GONE
iv_action.setColorFilter(ContextCompat.getColor(this@RichTextActivity, R.color.tintColor))
}
}
iv_action.setOnClickListener {
if (fl_action.visibility == View.VISIBLE) {
fl_action.visibility = View.GONE
iv_action.setColorFilter(ContextCompat.getColor(this@RichTextActivity, R.color.tintColor))
} else {
//                if (isKeyboardShowing) {
//                    KeyboardUtils.hideSoftInput(this@RichTextActivity)
//                }
KeyboardUtils.showSoftInput(this@RichTextActivity)
fl_action.visibility = View.VISIBLE
iv_action.setColorFilter(ContextCompat.getColor(this@RichTextActivity, R.color.colorPrimary))
}
}

主要的逻辑代码(RichTextActivity.kt):

class RichTextActivity :AppCompatActivity(), OnActionPerformListener {
private var popupWindow //编辑图片的pop
: CommonPopupWindow? = null
private var currentUrl=""
private val mEditorMenuFragment by lazy{ EditorMenuFragment(R.id.fl_action) }
private var isKeyboardShowing = false
private val inputLinkDialog by lazy { InputLinkDialog(this, sureListener = {href, name ->
againEdit()
rich_Editor.insertLink(href,name)
}) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rich_text)
initData()
}
private fun initData(){
initPop()
initEditor()
}
private fun initEditor() {
//输入框显示字体的大小
rich_Editor.setEditorFontSize(16)
//输入框显示字体的颜色
rich_Editor.setEditorFontColor(ContextCompat.getColor(this,R.color.deepGrey))
//输入框背景设置
rich_Editor.setEditorBackgroundColor(Color.WHITE)
//输入框文本padding
rich_Editor.setPadding(10, 10, 10, 10)
//输入提示文本
rich_Editor.setPlaceholder("点击输入正文!~")
//文本输入框监听事件
rich_Editor.setOnTextChangeListener { text -> Log.e("富文本文字变动", text!!) }
edit_name.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
tv_sum.text = edit_name.text.toString().length.toString()+"/100"
val html = rich_Editor.html
}
})
rich_Editor.setOnDecorationChangeListener { _, types ->
val flagArr = ArrayList<String>()
for (i in types.indices) {
flagArr.add(types[i].name)
}
if (flagArr.contains("BOLD")) {
button_bold.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.BOLD, true)
} else {
button_bold.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.BOLD, false)
}
if (flagArr.contains("ITALIC")) {
button_italic.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.ITALIC, true)
} else {
button_italic.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ITALIC, false)
}
if (flagArr.contains("STRIKETHROUGH")) {
button_strikethrough.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.STRIKETHROUGH, true)
} else {
button_strikethrough.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.STRIKETHROUGH, false)
}
if (flagArr.contains("JUSTIFYCENTER")) {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, true)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, false)
} else {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, false)
}
if (flagArr.contains("JUSTIFYLEFT")) {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, true)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, false)
} else {
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, false)
}
if (flagArr.contains("JUSTIFYRIGHT")) {
button_align_center.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_left.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_CENTER, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_LEFT, false)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, true)
} else {
button_align_right.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.JUSTIFY_RIGHT, false)
}
if (flagArr.contains("UNDERLINE")) {
button_underline.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
mEditorMenuFragment.updateActionStates(ActionType.UNDERLINE, true)
} else {
button_underline.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.UNDERLINE, false)
}
if (flagArr.contains("ORDEREDLIST")) {
button_list_ol.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_list_ul.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ORDERED, true)
mEditorMenuFragment.updateActionStates(ActionType.UNORDERED, false)
} else {
button_list_ol.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ORDERED, false)
}
if (flagArr.contains("UNORDEREDLIST")) {
button_list_ul.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.colorPrimary
)
)
button_list_ol.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.ORDERED, false)
mEditorMenuFragment.updateActionStates(ActionType.UNORDERED, true)
} else {
button_list_ul.setColorFilter(
ContextCompat.getColor(
this@RichTextActivity,
R.color.tintColor
)
)
mEditorMenuFragment.updateActionStates(ActionType.UNORDERED, false)
}
}
rich_Editor.setImageClickListener { imageUrl ->
currentUrl = imageUrl
popupWindow?.showBottom(ll_container, 0.5f)
}
button_rich_do.setOnClickListener { rich_Editor.redo() }
button_rich_undo.setOnClickListener { rich_Editor.undo()}
button_bold.setOnClickListener {
againEdit()
rich_Editor.setBold() }
button_underline.setOnClickListener {
againEdit()
rich_Editor.setUnderline()
}
button_italic.setOnClickListener {
againEdit()
rich_Editor.setItalic()
}
button_strikethrough.setOnClickListener {
againEdit()
rich_Editor.setStrikeThrough()
}
//字号
button_h1.setOnClickListener {
againEdit()
rich_Editor.setFontSize(2)
}
button_h2.setOnClickListener {
againEdit()
rich_Editor.setFontSize(3)
}
button_h3.setOnClickListener {
againEdit()
rich_Editor.setFontSize(4)
}
button_h4.setOnClickListener {
againEdit()
rich_Editor.setFontSize(5)
}
button_indent_decrease.setOnClickListener {
againEdit()
rich_Editor.setOutdent()
}
button_indent_increase.setOnClickListener {
againEdit()
rich_Editor.setIndent()
}
button_list_ul.setOnClickListener {
againEdit()
rich_Editor.setBullets()
}
button_list_ol.setOnClickListener {
againEdit()
rich_Editor.setNumbers()
}
button_align_center.setOnClickListener {
againEdit()
rich_Editor.setAlignCenter()
}
button_align_left.setOnClickListener {
againEdit()
rich_Editor.setAlignLeft()
}
button_align_right.setOnClickListener {
againEdit()
rich_Editor.setAlignRight()
}
button_link.setOnClickListener {
KeyboardUtils.hideSoftInput(this@RichTextActivity)
inputLinkDialog.show()
}
//选择图片
button_image.setOnClickListener {
selectImage()
}
//选择视频
button_video.setOnClickListener {
selectVideo()
}
mEditorMenuFragment.setActionClickListener(this)
supportFragmentManager.beginTransaction().add(R.id.fl_action, mEditorMenuFragment, EditorMenuFragment::class.java.name).commit()
KeyboardUtils.registerSoftInputChangedListener(this) { height: Int ->
//键盘打开
isKeyboardShowing = height > 0
if (height > 0) {
//fl_action.visibility = View.GONE
val params = fl_action.layoutParams
params.height = height/2
fl_action.layoutParams = params
} else{
//if (fl_action.visibility != View.VISIBLE)
fl_action.visibility = View.GONE
iv_action.setColorFilter(ContextCompat.getColor(this@RichTextActivity, R.color.tintColor))
}
}
iv_action.setOnClickListener {
if (fl_action.visibility == View.VISIBLE) {
fl_action.visibility = View.GONE
iv_action.setColorFilter(ContextCompat.getColor(this@RichTextActivity, R.color.tintColor))
} else {
//                if (isKeyboardShowing) {
//                    KeyboardUtils.hideSoftInput(this@RichTextActivity)
//                }
KeyboardUtils.showSoftInput(this@RichTextActivity)
fl_action.visibility = View.VISIBLE
iv_action.setColorFilter(ContextCompat.getColor(this@RichTextActivity, R.color.colorPrimary))
}
}
}
private fun initPop() {
val view= LayoutInflater.from(this@RichTextActivity).inflate(R.layout.pop_picture, null)
view.findViewById<View>(R.id.linear_cancle)
.setOnClickListener { popupWindow?.dismiss() }
view.findViewById<View>(R.id.linear_delete_pic).setOnClickListener { v: View? ->
//删除图片
val removeUrl =
"<img src=https://blog.csdn.net/T01151018/article/details/\"$currentUrl\" alt=\"dachshund\" width=\"80%\">
"
val newUrl: String = rich_Editor.html.replace(removeUrl, "") currentUrl = "" rich_Editor.html = newUrl if (RichUtils.isEmpty(rich_Editor.html)) { rich_Editor.html = "" } popupWindow?.dismiss() } popupWindow = CommonPopupWindow.Builder(this@RichTextActivity) .setView(view) .setWidthAndHeight( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ) .setOutsideTouchable(true) //在外不可用手指取消 .setAnimationStyle(R.style.pop_animation) //设置popWindow的出场动画 .create() popupWindow?.setOnDismissListener(PopupWindow.OnDismissListener { rich_Editor.setInputEnabled( true ) }) } private fun againEdit() { //如果第一次点击例如加粗,没有焦点时,获取焦点并弹出软键盘 rich_Editor.focusEditor() KeyBoardUtils.openKeyboard(edit_name, this@RichTextActivity) } override fun onActionPerform(type: ActionType?, vararg values: Any?) { var value = "" if (values != null && values.isNotEmpty()) { value = values[0] as String } againEdit() when (type) { ActionType.FORE_COLOR -> { rich_Editor.setTextColor(value)} ActionType.BOLD -> { rich_Editor.setBold()} ActionType.ITALIC -> rich_Editor.setItalic() ActionType.UNDERLINE -> rich_Editor.setUnderline() ActionType.STRIKETHROUGH -> rich_Editor.setStrikeThrough() ActionType.H1 -> { rich_Editor.setFontSize(2) mEditorMenuFragment.updateActionStates(ActionType.H1,true) mEditorMenuFragment.updateActionStates(ActionType.H2,false) mEditorMenuFragment.updateActionStates(ActionType.H3,false) mEditorMenuFragment.updateActionStates(ActionType.H4,false) } ActionType.H2 -> { rich_Editor.setFontSize(3) mEditorMenuFragment.updateActionStates(ActionType.H1,false) mEditorMenuFragment.updateActionStates(ActionType.H2,true) mEditorMenuFragment.updateActionStates(ActionType.H3,false) mEditorMenuFragment.updateActionStates(ActionType.H4,false) } ActionType.H3 -> { rich_Editor.setFontSize(4) mEditorMenuFragment.updateActionStates(ActionType.H1,false) mEditorMenuFragment.updateActionStates(ActionType.H2,false) mEditorMenuFragment.updateActionStates(ActionType.H3,true) mEditorMenuFragment.updateActionStates(ActionType.H4,false) } ActionType.H4 -> { rich_Editor.setFontSize(5) mEditorMenuFragment.updateActionStates(ActionType.H1,false) mEditorMenuFragment.updateActionStates(ActionType.H2,false) mEditorMenuFragment.updateActionStates(ActionType.H3,false) mEditorMenuFragment.updateActionStates(ActionType.H4,true) } ActionType.JUSTIFY_LEFT -> rich_Editor.setAlignLeft() ActionType.JUSTIFY_CENTER -> rich_Editor.setAlignCenter() ActionType.JUSTIFY_RIGHT -> rich_Editor.setAlignRight() ActionType.INDENT -> rich_Editor.setIndent() ActionType.OUTDENT -> rich_Editor.setOutdent() ActionType.UNORDERED->rich_Editor.setBullets() ActionType.ORDERED->rich_Editor.setNumbers() ActionType.IMAGE -> { selectImage() } ActionType.LINK -> { KeyboardUtils.hideSoftInput(this@RichTextActivity) inputLinkDialog.show() } ActionType.VIDEO -> { selectVideo() } else -> {} } } // 以下图片视频地址,来自网络素材 fun selectImage(){ // 进入相册选择照片之后可以本地文件直接插入html,或者上传到服务器获取地址再插入html中 val path="https://upload-images.jianshu.io/upload_images/5809200-a99419bb94924e6d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" againEdit() rich_Editor.insertImage(path, "dachshund") KeyBoardUtils.openKeyboard(edit_name, this@RichTextActivity) } fun selectVideo(){ // 选择视频之后可以本地文件直接插入html,或者上传到服务器获取地址再插入html中 val path="https://media.w3.org/2010/05/sintel/trailer.mp4" againEdit() rich_Editor.insertVideoPercentage(path, "80%","30%") KeyBoardUtils.openKeyboard(edit_name, this@RichTextActivity) } }

4. 完整代码

完整代码我已上传github,需要的可以自行pull:https://github.com/FullCourage/RichEditor


总结

这个功能是之前做的,时间间隔有点久了,有些细微的点已经记不得了,由此事后的总结记录就格外重要。

本站无任何商业行为
个人在线分享-虚灵IT资料分享 » 【Android】基于webView打造富文本编辑器(H5)
E-->