RichEditor

基于原生EditText+span实现的Android富文本编辑器
github地址:https://github.com/yuruiyin/RichEditor

组件描述

该组件是基于原生EditText+span的方式实现的,旨在提供一个功能齐全且使用方便的Android富文本编辑器。主要支持了加粗斜体等行内样式、标题引用等段内样式以及插入图片视频甚至自定义View等。

功能演示

Video_20190521_122847_513.gif

功能列表

  • 支持加粗、斜体、删除线、下划线行内样式
  • 支持插入标题、引用段内样式
  • 支持插入段落图片、视频
  • 支持插入段落自定义布局
  • 支持视频、gif和长图标记
  • 支持图片圆角
  • undo redo
  • [TODO] 支持行内ImageSpan,如类似微博@xxx,#话题名#
  • [TODO] 支持清除样式
  • [TODO] 编辑器内部复制粘贴ImageSpan(任意以ImageSpan方式插入的的类型,如图片、视频、自定义view等)

如何使用

gradle

Step 1. Add the JitPack repository in your root build.gradle at the end of repositories:

allprojects {    repositories {        ...        maven { url 'https://jitpack.io' }    }}

Step 2. Add the dependency in your app build.gradle:

dependencies {    implementation 'com.github.yuruiyin:RichEditor:0.1.0'}

参数定义

自定义属性名字 参数定义
editor_show_video_mark 是否显示视频标识图标
editor_video_mark_resource_id 视频图标资源id
editor_show_gif_mark 是否显示gif标识图标
editor_show_long_image_mark 是否显示长图标识
editor_image_radius 图片和视频圆角大小
editor_headline_text_size 标题字体大小

代码演示

说明:各个样式按钮的layout由调用方自行完成

1) 首先在xml中引用RichEditText:

2) 针对加粗、斜体、标题等需要修改图标样式的按钮(不包括插入图片按钮),如加粗,处理如下:

    // 加粗    richEditText.initStyleButton(            StyleBtnVm(                    RichTypeEnum.BOLD,                    ivBold,                    R.mipmap.icon_bold_normal,                    R.mipmap.icon_bold_light            )    )

说明:其中ivBold为加粗ImageView,由调用方在layout中定义;R.mipmap.icon_bold_normal和R.mipmap.icon_bold_light是加粗按钮正常状态和点亮状态图片的资源id。

3)插入图片或视频

    /**     * 处理插入图片     */    private fun handleAddImage() {        val intent = Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI)        startActivityForResult(intent, GET_PHOTO_REQUEST_CODE)    }    private fun doAddBlockImageSpan(            realImagePath: String, blockImageSpanObtainObject: IBlockImageSpanObtainObject, isFromDraft: Boolean = false    ) {//        val blockImageSpanVm = BlockImageSpanVm(this, imageVm) // 不指定宽高,使用组件默认宽高        val blockImageSpanVm =                BlockImageSpanVm(blockImageSpanObtainObject, imageWidth, imageMaxHeight) // 指定宽高        blockImageSpanVm.isFromDraft = isFromDraft        richEditText.insertBlockImage(realImagePath, blockImageSpanVm) { blockImageSpan ->            val spanObtainObject = blockImageSpan.blockImageSpanVm.spanObject            when (spanObtainObject) {                is ImageVm -> {                    Toast.makeText(this, "短按了图片-当前图片路径:${spanObtainObject.path}", Toast.LENGTH_SHORT).show()                }                is VideoVm -> {                    Toast.makeText(this, "短按了视频-当前视频路径:${spanObtainObject.path}", Toast.LENGTH_SHORT).show()                }            }        }    }    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        super.onActivityResult(requestCode, resultCode, data)        if (requestCode == GET_PHOTO_REQUEST_CODE && resultCode == RESULT_OK && data != null) {            // 相册图片返回            val selectedImageUri = data.data ?: return            val realImagePath = FileUtil.getFileRealPath(this, selectedImageUri) ?: return            val fileType = FileUtil.getFileType(realImagePath) ?: return            when (fileType) {                FileTypeEnum.STATIC_IMAGE, FileTypeEnum.GIF -> {                    val imageVm = ImageVm(realImagePath, "2")                    doAddBlockImageSpan(realImagePath, imageVm)                }                FileTypeEnum.VIDEO -> {                    // 插入视频封面                    val videoVm = VideoVm(realImagePath, "3")                    doAddBlockImageSpan(realImagePath, videoVm)                }            }        }    }    

4) 插入自定义布局

    /**     * 插入游戏     */    private fun handleAddGame() {        val gameVm = GameVm(1, "一起来捉妖")        doAddGame(gameVm)    }    private fun doAddGame(gameVm: GameVm, isFromDraft: Boolean = false) {        val gameItemView = layoutInflater.inflate(R.layout.editor_game_item, null)        val ivGameIcon = gameItemView.findViewById(R.id.ivGameIcon)        val tvGameName = gameItemView.findViewById(R.id.tvGameName)        ivGameIcon.setImageResource(R.mipmap.icon_game_zhuoyao)        tvGameName.text = gameVm.name        ivGameIcon.layoutParams.width = gameIconSize        ivGameIcon.layoutParams.height = gameIconSize        val gameItemWidth = getEditTextWidthWithoutPadding()        ViewUtil.layoutView(gameItemView, gameItemWidth, gameItemHeight)        val blockImageSpanVm = BlockImageSpanVm(gameVm, gameItemWidth, imageMaxHeight)        blockImageSpanVm.isFromDraft = isFromDraft        richEditText.insertBlockImage(ViewUtil.getBitmap(gameItemView), blockImageSpanVm) { blockImageSpan ->            val retGameVm = blockImageSpan.blockImageSpanVm.spanObject as GameVm            // 点击游戏item            Toast.makeText(this, "短按了游戏:${retGameVm.name}", Toast.LENGTH_SHORT).show()        }    }    

说明:插入自定义布局最终也是通过bitmap以ImageSpan的形式插入到编辑器中的。

5)获取数据

    // 返回的编辑器实体是一个list,list中每个元素代表一个段落block,具体block参数可以参考RichEditorBlock,     // 但是若需要保存草稿功能,则需要对该list进行转换成自己的实体,否则List序列化后反序列化会丢失数据,可以参考demo    val conntent: List = richEditText.content

具体使用请参考demo

相关引用

  1. 设置EditText的光标高度: LineHeightEditText
  2. 设置图片圆角: RoundedImageView
  3. undo redo: AndroidEdit

最后

再次附上github地址:https://github.com/yuruiyin/RichEditor
欢迎star、fork、提issue~

更多相关文章

  1. Android——插入图片【ImageView】属性详解
  2. android图片透明度跟缩放大小动画事件
  3. Android中自定义标题栏样式的两种方法
  4. Android中自定义下拉样式Spinner
  5. Android样式基础--drawable篇
  6. Android中简单实现选择图片并裁剪
  7. FFmpeg+OpenSL+OpenGL+Mediacodec 的视频播放SDK源码和实例APP
  8. Android基于tess-two的离线身份证等图片文字识别
  9. Android中VideoView播放当前工程中视频文件的方法

随机推荐

  1. MySQL嵌套事务所遇到的问题
  2. 记一次因线上mysql优化器误判引起慢查询
  3. MySql Sql 优化技巧分享
  4. 利用ssh tunnel链接mysql服务器的方法
  5. mysql 全文检索中文解决方法及实例代码
  6. 浅谈mysql可有类似oracle的nvl的函数
  7. 浅谈Mysql中类似于nvl()函数的ifnull()函
  8. Window下Mysql忘记root密码怎么重置
  9. 一次Mysql死锁排查过程的全纪录
  10. Windows10 64位安装MySQL5.6.35的图文教