安卓文本编辑器php cpp,开源的Android富文本编辑器

RichEditor

基于原生EditText+span实现的Android富文本编辑器

github地址:https://github.com/yuruiyin/RichEditor

组件描述

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

功能演示

421b53fa839d

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:

android:id="@+id/richEditText"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:background="#ffffff"

android:gravity="top|left"

android:hint="请输入..."

android:inputType="textMultiLine"

android:lineSpacingExtra="5dp"

android:maxLength="20000"

android:minHeight="350dp"

android:paddingBottom="70dp"

android:paddingLeft="15dp"

android:paddingRight="15dp"

android:paddingTop="23dp"

android:textColor="#171717"

android:textColorHint="#aaaaaa"

android:textCursorDrawable="@null"

android:textSize="16dp"

app:editor_video_mark_resource_id="@mipmap/editor_video_mark_icon"

app:editor_image_radius="3dp"

app:editor_show_gif_mark="true"

app:editor_show_video_mark="true"

app:editor_show_long_image_mark="true"

/>

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

相关引用

最后

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python gif 透明,Python3+试点批量处理简单的GIF到PNG并透明地去除背景色,python3Pillow,gif,转成,png,透明化,去掉...

1. 安装Pillow, 只用这个应该也可以,2. 安装 cImage下载后解压,拷贝image.py到你python安装目录的 Lib\site-packages 中。from PIL import Imageimport osimport imagedef get_imlist(path):"""返回目录中所有gif图像的文件名列表图像的…

matlab求半衰期,如何使用GLD和GDX价差来估计均值回归的半衰期

计算均值回归时间序列的半衰期我们可以通过例中GLD和GDX的均值回归差价来计算均值回归半衰期。MATLAB代码可以从epchan. com/book/example? _ 5. m获得。(这个程序的第一部分与example7 2. m.相同。)%在此播入example7_2. m%Insert example7 2. m in the beginning hereprevzb…

框架错误汇总

1.struts标签&#xff0c;在body中输入代码发现值栈不存在&#xff0c; 即<s:debug></s:debug>没有起作用 1 <body>2 3 4 测试url标签<br>5 <s:url value"index.jsp" var"surl"></s:url><br>6 <s:url value&…

初次进入oracle数据库,Oracle数据库的初次使用

oracle数据库的初次使用&#xff1a;oracle自带了用户 system /system管理员用户 scott/tiger用户初次使用&#xff1a;创建表空间(此处为使用默认的用户scott/tiger)在控制台&#xff1a;1.使用system/system用户登录语句&#xff1a;sqlplus system/system2.赋予用户权限&…

oracle+循环插入sql,SQL server,Oracle循环插入百万数据

SQL server&#xff0c;Oracle循环插入百万数据SQL server&#xff0c;Oracle循环插入百万数据压测时常需要往数据库插入大量数据&#xff0c;下面是我往两个数据库插入数据时用的脚本declare maxSum int,lid nvarchar(64), -- lid为表idcid int,userid nvarchar(64),oper_time…

jquery 通过submit()方法 提交表单示例

jquery 通过submit()方法 提交表单示例&#xff1a; 本示例&#xff1a;以用户注册作为例子。使用jquery中的submit()方法实现表单提交。 注&#xff1a;本示例仅提供了对表单的验证&#xff0c;本例只用选用了三个字段作为测试。 用户点击提交按钮时&#xff0c;触发点击事件&…

php background-image,css background-image属性怎么用

css background-image属性为元素设置背景图像&#xff0c;语法为&#xff1a;background-image:url(图片路径)。设置的背景图像会占据元素的全部尺寸&#xff0c;包括内边距和边框&#xff0c;但不包括外边距。css background-image属性怎么用&#xff1f;作用&#xff1a;为元…

webstorm

问题描述&#xff1a;webstorm打开文件夹&#xff0c;文件夹内的文件不能全部显示&#xff0c;如图 原因&#xff1a;配置文件xml出错 解决方法&#xff1a;删除文件夹内的idea文件&#xff0c;再用webstrom重新打开就行╮(╯▽╰)╭转载于:https://www.cnblogs.com/chenluomen…

linux文件句柄数满,linux文件句柄数超出系统限制怎么办?

1、问题阐述&#xff1a;too many open files&#xff1a;顾名思义即打开过多文件数。不过这里的files不单是文件的意思&#xff0c;也包括打开的通讯链接(比如socket)&#xff0c;正在监听的端口等等&#xff0c;所以有时候也可以叫做句柄(handle)&#xff0c;这个错误通常也可…

linux 内核编译不能打字,linux系统升级后,手动编译的kernel无法启动问题

linux系统升级后&#xff0c;手动编译的kernel无法启动问题linux系统升级后&#xff0c;手动编译的kernel无法启动问题做开发相关&#xff0c;需要编译3.18的kernel&#xff0c;x86_64的&#xff0c;但是我的deepin升级v20之后&#xff0c;编译的kernel就无法启动了&#xff0c…

arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)

前言 关于本篇功能实现用到的 api 涉及类看不懂的&#xff0c;请参照 esri 官网的 arcgis api 3.x for js&#xff1a;esri 官网 api&#xff0c;里面详细的介绍 arcgis api 3.x 各个类的介绍&#xff0c;还有就是在线例子&#xff1a;esri 官网在线例子&#xff0c;这个也是学…

SVN版本管理trunk及branch相关merge操作

先说说什么是branch。按照Subversion的说法&#xff0c;一个branch是某个development line&#xff08;通常是主线也即trunk&#xff09;的一个拷贝&#xff0c;见下图&#xff1a; branch存在的意义在于&#xff0c;在不干扰trunk的情况下&#xff0c;和trunk并行开发&#xf…

线程之间通信 等待(wait)和通知(notify)

线程通信概念&#xff1a; 线程是操作系统中独立的个体&#xff0c;但这些个体如果不经过特殊的处理就不能成为一个整体&#xff0c;线程之间的通信就成为整体的必用方式之一。当线程存在通信指挥&#xff0c;系统间的交互性会更强大&#xff0c;在提高CPU利用率的同时还会对线…

女生适合linux运维吗,女生适不适合做Linux运维工程师进入IT行业?

很多人对于女生做Linux运维工程师进入IT还有都存在质疑。因为大多数人认为女生不适合IT行业&#xff0c;IT is a men’sworld&#xff0c;女生学IT是件匪夷所思的事情。在传统的思维当中&#xff0c;女生只适合从事像教师、会计、公务员等稳定的职业。然而&#xff0c;这一莫名…

WPF强制更新

&#xff0c;更新的时候选择最小版本号,就是强制更新 转载于:https://www.cnblogs.com/damsoft/p/6119509.html

a的n次方的最后三位数c语言,求13的n次方(12n≤130000000000)的最后三位数,用c++编程...

#includeintmain(){longlonginti,x,y,last;/*变量last保存求X的Y次方过程中的部分乘积的后三位*///输入while(scanf("%lld,%lld",&x,&y)2){last1;x%1000;//因为一个三位数的n次方的最后三位数只和这个数的最后三位数有关y%100;//因为可以发现这个是一个轮回&…

Selenium2+python自动化5-操作浏览器基本方法

前言 前面已经把环境搭建好了&#xff0c;这从这篇开始&#xff0c;正式学习selenium的webdriver框架。我们平常说的 selenium自动化&#xff0c;其实它并不是类似于QTP之类的有GUI界面的可视化工具&#xff0c;我们要学的是webdriver框架的API。 本篇主要讲如何用Python调用we…

deepin20自带c语言,deepin 20.1终于找到你-国产操作系统deepin之初体验

deepin 20.1终于找到你-国产操作系统deepin之初体验前几天刚安装了国产操作系统deepin20.1&#xff0c;使用了几天体验非常好&#xff0c;推荐大家安装使用。这款操作系统确实做的很用心&#xff0c;很不错。日常使用、办公学习、影音娱乐已经完全可以替代Win了。界面简洁友好上…

c语言链表内存分配失败,链表的C语言实现之动态内存分配

链表的C语言实现之动态内存分配來源:互聯網 2008-06-01 02:05:07 評論一、为什么用动态内存分配但我们未学习链表的时候&#xff0c;假如要存储数量比较多的同类型或同结构的数据的时候&#xff0c;总是使用一个数组。比如说我们要存储一个班级学生的某科分数&#xff0c;总是…

android分享图片功能实现原理,Android:简单实现并理解图片三级缓存

学习Android网络开发的过程中&#xff0c;势必会经历很多痛苦的过程&#xff0c;其中一个大坑就是图片缓存&#xff0c;当然现在有很多现成的库非常方便&#xff0c;常常几行代码就可以实现想要的功能&#xff0c;但不懂其中的原理是不行的&#xff0c;所以对于刚开始学习网络编…