代码地址如下:
http://www.demodashi.com/demo/14883.html

一、运行效果图

二、代码具体实现

1.引入richeditor-android
  1. richeditor-android需要的jar
  2. implementation 'jp.wasabeef:richeditor-android:1.2.2'
  3. 这是一个Dialog框架,demo中不想自己去写,所以就使用了第三方
  4. implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
2.引入控件RichEditor
  1. <jp.wasabeef.richeditor.RichEditor
  2. android:id="@+id/editor"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content" />
3.使用到的权限

如果拍照需要相机权限,选择图片需要SD卡权限,插入网络图片需要网络权限

  1. <uses-permission android:name="android.permission.CAMERA" />
  2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  4. <uses-permission android:name="android.permission.INTERNET" />
4.初始化RichEditor
  1. mEditor = (RichEditor) findViewById(R.id.editor);
  2. //初始化编辑高度
  3. mEditor.setEditorHeight(200);
  4. //初始化字体大小
  5. mEditor.setEditorFontSize(22);
  6. //初始化字体颜色
  7. mEditor.setEditorFontColor(Color.BLACK);
  8. //mEditor.setEditorBackgroundColor(Color.BLUE);
  9. //初始化内边距
  10. mEditor.setPadding(10, 10, 10, 10);
  11. //设置编辑框背景,可以是网络图片
  12. //mEditor.setBackground("https://raw.githubusercontent.com/wasabeef/art/master/chip.jpg");
  13. // mEditor.setBackgroundColor(Color.BLUE);
  14. mEditor.setBackgroundResource(R.drawable.bg);
  15. //设置默认显示语句
  16. mEditor.setPlaceholder("Insert text here...");
  17. //设置编辑器是否可用
  18. mEditor.setInputEnabled(true);
5.实时监听Editor输入内容
  1. mPreview = (TextView) findViewById(R.id.preview);
  2. mEditor.setOnTextChangeListener(new RichEditor.OnTextChangeListener() {
  3. @Override
  4. public void onTextChange(String text) {
  5. mPreview.setText(text);
  6. }
  7. });
6.功能方法
  1. /**
  2. * 撤销当前标签状态下所有内容
  3. */
  4. findViewById(R.id.action_undo).setOnClickListener(new View.OnClickListener() {
  5. @Override
  6. public void onClick(View v) {
  7. mEditor.undo();
  8. }
  9. });
  10. /**
  11. * 恢复撤销的内容
  12. */
  13. findViewById(R.id.action_redo).setOnClickListener(new View.OnClickListener() {
  14. @Override
  15. public void onClick(View v) {
  16. mEditor.redo();
  17. }
  18. });
  19. /**
  20. * 加粗
  21. */
  22. findViewById(R.id.action_bold).setOnClickListener(new View.OnClickListener() {
  23. @Override
  24. public void onClick(View v) {
  25. mEditor.focusEditor();
  26. mEditor.setBold();
  27. }
  28. });
  29. /**
  30. * 斜体
  31. */
  32. findViewById(R.id.action_italic).setOnClickListener(new View.OnClickListener() {
  33. @Override
  34. public void onClick(View v) {
  35. mEditor.focusEditor();
  36. mEditor.setItalic();
  37. }
  38. });
  39. /**
  40. * 下角表
  41. */
  42. findViewById(R.id.action_subscript).setOnClickListener(new View.OnClickListener() {
  43. @Override
  44. public void onClick(View v) {
  45. mEditor.focusEditor();
  46. if (mEditor.getHtml() == null) {
  47. return;
  48. }
  49. mEditor.setSubscript();
  50. }
  51. });
  52. /**
  53. * 上角标
  54. */
  55. findViewById(R.id.action_superscript).setOnClickListener(new View.OnClickListener() {
  56. @Override
  57. public void onClick(View v) {
  58. mEditor.focusEditor();
  59. if (mEditor.getHtml() == null) {
  60. return;
  61. }
  62. mEditor.setSuperscript();
  63. }
  64. });
  65. /**
  66. * 删除线
  67. */
  68. findViewById(R.id.action_strikethrough).setOnClickListener(new View.OnClickListener() {
  69. @Override
  70. public void onClick(View v) {
  71. mEditor.focusEditor();
  72. mEditor.setStrikeThrough();
  73. }
  74. });
  75. /**
  76. *下划线
  77. */
  78. findViewById(R.id.action_underline).setOnClickListener(new View.OnClickListener() {
  79. @Override
  80. public void onClick(View v) {
  81. mEditor.focusEditor();
  82. mEditor.setUnderline();
  83. }
  84. });
  85. /**
  86. * 设置标题(1到6)
  87. */
  88. findViewById(R.id.action_heading1).setOnClickListener(new View.OnClickListener() {
  89. @Override
  90. public void onClick(View v) {
  91. mEditor.setHeading(1);
  92. }
  93. });
  94. findViewById(R.id.action_heading2).setOnClickListener(new View.OnClickListener() {
  95. @Override
  96. public void onClick(View v) {
  97. mEditor.setHeading(2);
  98. }
  99. });
  100. findViewById(R.id.action_heading3).setOnClickListener(new View.OnClickListener() {
  101. @Override
  102. public void onClick(View v) {
  103. mEditor.setHeading(3);
  104. }
  105. });
  106. findViewById(R.id.action_heading4).setOnClickListener(new View.OnClickListener() {
  107. @Override
  108. public void onClick(View v) {
  109. mEditor.setHeading(4);
  110. }
  111. });
  112. findViewById(R.id.action_heading5).setOnClickListener(new View.OnClickListener() {
  113. @Override
  114. public void onClick(View v) {
  115. mEditor.setHeading(5);
  116. }
  117. });
  118. findViewById(R.id.action_heading6).setOnClickListener(new View.OnClickListener() {
  119. @Override
  120. public void onClick(View v) {
  121. mEditor.setHeading(6);
  122. }
  123. });
  124. /**
  125. * 设置字体颜色
  126. */
  127. findViewById(R.id.action_txt_color).setOnClickListener(new View.OnClickListener() {
  128. @Override
  129. public void onClick(View v) {
  130. mEditor.focusEditor();
  131. new MaterialDialog.Builder(MainActivity.this)
  132. .title("选择字体颜色")
  133. .items(R.array.color_items)
  134. .itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() {
  135. @Override
  136. public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
  137. dialog.dismiss();
  138. switch (which) {
  139. case 0://红
  140. mEditor.setTextColor(Color.RED);
  141. break;
  142. case 1://黄
  143. mEditor.setTextColor(Color.YELLOW);
  144. break;
  145. case 2://蓝
  146. mEditor.setTextColor(Color.GREEN);
  147. break;
  148. case 3://绿
  149. mEditor.setTextColor(Color.BLUE);
  150. break;
  151. case 4://黑
  152. mEditor.setTextColor(Color.BLACK);
  153. break;
  154. }
  155. return false;
  156. }
  157. }).show();
  158. }
  159. });
  160. findViewById(R.id.action_bg_color).setOnClickListener(new View.OnClickListener() {
  161. @Override
  162. public void onClick(View v) {
  163. mEditor.focusEditor();
  164. new MaterialDialog.Builder(MainActivity.this)
  165. .title("选择字体背景颜色")
  166. .items(R.array.text_back_color_items)
  167. .itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() {
  168. @Override
  169. public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
  170. dialog.dismiss();
  171. switch (which) {
  172. case 0://红
  173. mEditor.setTextBackgroundColor(Color.RED);
  174. break;
  175. case 1://黄
  176. mEditor.setTextBackgroundColor(Color.YELLOW);
  177. break;
  178. case 2://蓝
  179. mEditor.setTextBackgroundColor(Color.GREEN);
  180. break;
  181. case 3://绿
  182. mEditor.setTextBackgroundColor(Color.BLUE);
  183. break;
  184. case 4://黑
  185. mEditor.setTextBackgroundColor(Color.BLACK);
  186. break;
  187. case 5://透明
  188. mEditor.setTextBackgroundColor(R.color.transparent);
  189. break;
  190. }
  191. return false;
  192. }
  193. }).show();
  194. }
  195. });
  196. /**
  197. * 向右缩进
  198. */
  199. findViewById(R.id.action_indent).setOnClickListener(new View.OnClickListener() {
  200. @Override
  201. public void onClick(View v) {
  202. mEditor.focusEditor();
  203. mEditor.setIndent();
  204. }
  205. });
  206. /**
  207. * 向左缩进
  208. */
  209. findViewById(R.id.action_outdent).setOnClickListener(new View.OnClickListener() {
  210. @Override
  211. public void onClick(View v) {
  212. mEditor.focusEditor();
  213. mEditor.setOutdent();
  214. }
  215. });
  216. /**
  217. *文章左对齐
  218. */
  219. findViewById(R.id.action_align_left).setOnClickListener(new View.OnClickListener() {
  220. @Override
  221. public void onClick(View v) {
  222. mEditor.focusEditor();
  223. mEditor.setAlignLeft();
  224. }
  225. });
  226. /**
  227. * 文章居中对齐
  228. */
  229. findViewById(R.id.action_align_center).setOnClickListener(new View.OnClickListener() {
  230. @Override
  231. public void onClick(View v) {
  232. mEditor.setAlignCenter();
  233. }
  234. });
  235. /**
  236. * 文章右对齐
  237. */
  238. findViewById(R.id.action_align_right).setOnClickListener(new View.OnClickListener() {
  239. @Override
  240. public void onClick(View v) {
  241. mEditor.setAlignRight();
  242. }
  243. });
  244. /**
  245. * 无序排列
  246. */
  247. findViewById(R.id.action_insert_bullets).setOnClickListener(new View.OnClickListener() {
  248. @Override
  249. public void onClick(View v) {
  250. mEditor.setBullets();
  251. }
  252. });
  253. /**
  254. * 有序排列
  255. */
  256. findViewById(R.id.action_insert_numbers).setOnClickListener(new View.OnClickListener() {
  257. @Override
  258. public void onClick(View v) {
  259. mEditor.setNumbers();
  260. }
  261. });
  262. /**
  263. * 引用
  264. */
  265. findViewById(R.id.action_blockquote).setOnClickListener(new View.OnClickListener() {
  266. @Override
  267. public void onClick(View v) {
  268. mEditor.setBlockquote();
  269. }
  270. });
  271. /**
  272. * 插入图片
  273. */
  274. findViewById(R.id.action_insert_image).setOnClickListener(new View.OnClickListener() {
  275. @Override
  276. public void onClick(View v) {
  277. mEditor.focusEditor();
  278. ActivityCompat.requestPermissions(MainActivity.this, mPermissionList, 100);
  279. }
  280. });
  281. /**
  282. * 插入连接
  283. */
  284. findViewById(R.id.action_insert_link).setOnClickListener(new View.OnClickListener() {
  285. @Override
  286. public void onClick(View v) {
  287. new MaterialDialog.Builder(MainActivity.this)
  288. .title("将输入连接地址")
  289. .items("http://blog.csdn.net/huangxiaoguo1")
  290. .itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() {
  291. @Override
  292. public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
  293. dialog.dismiss();
  294. mEditor.focusEditor();
  295. mEditor.insertLink("http://blog.csdn.net/huangxiaoguo1",
  296. "http://blog.csdn.net/huangxiaoguo1");
  297. return false;
  298. }
  299. }).show();
  300. }
  301. });
  302. /**
  303. * 选择框
  304. */
  305. findViewById(R.id.action_insert_checkbox).setOnClickListener(new View.OnClickListener() {
  306. @Override
  307. public void onClick(View v) {
  308. mEditor.focusEditor();
  309. mEditor.insertTodo();
  310. }
  311. });
  312. /**
  313. * 获取并显示Html
  314. */
  315. findViewById(R.id.tv_showhtml).setOnClickListener(new View.OnClickListener() {
  316. @Override
  317. public void onClick(View v) {
  318. Intent intent = new Intent(v.getContext(), WebViewActivity.class);
  319. intent.putExtra("contextURL", mEditor.getHtml());
  320. startActivity(intent);
  321. }
  322. });
7.插入图片并使用屏幕宽度

  1. 权限,我这里只是选着图片,关于拍照的自己可以去实现
  2. String[] mPermissionList = new String[]{
  3. Manifest.permission.WRITE_EXTERNAL_STORAGE,
  4. Manifest.permission.READ_EXTERNAL_STORAGE};
  1. @Override
  2. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  3. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  4. switch (requestCode) {
  5. case 100:
  6. boolean writeExternalStorage = grantResults[0] == PackageManager.PERMISSION_GRANTED;
  7. boolean readExternalStorage = grantResults[1] == PackageManager.PERMISSION_GRANTED;
  8. if (grantResults.length > 0 && writeExternalStorage && readExternalStorage) {
  9. getImage();
  10. } else {
  11. Toast.makeText(this, "请设置必要权限", Toast.LENGTH_SHORT).show();
  12. }
  13. break;
  14. }
  15. }
  16. private void getImage() {
  17. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  18. startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT).setType("image/*"),
  19. REQUEST_PICK_IMAGE);
  20. } else {
  21. Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
  22. intent.addCategory(Intent.CATEGORY_OPENABLE);
  23. intent.setType("image/*");
  24. startActivityForResult(intent, REQUEST_PICK_IMAGE);
  25. }
  26. }
  27. @Override
  28. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  29. super.onActivityResult(requestCode, resultCode, data);
  30. if (resultCode == Activity.RESULT_OK) {
  31. switch (requestCode) {
  32. case REQUEST_PICK_IMAGE:
  33. if (data != null) {
  34. String realPathFromUri = RealPathFromUriUtils.getRealPathFromUri(this, data.getData());
  35. mEditor.insertImage("https://unsplash.it/2000/2000?random&58",
  36. "huangxiaoguo\" style=\"max-width:100%");
  37. mEditor.insertImage(realPathFromUri, realPathFromUri + "\" style=\"max-width:100%");
  38. // mEditor.insertImage(realPathFromUri, realPathFromUri + "\" style=\"max-width:100%;max-height:100%");
  39. } else {
  40. Toast.makeText(this, "图片损坏,请重新选择", Toast.LENGTH_SHORT).show();
  41. }
  42. break;
  43. }
  44. }
  45. }

注意这里 “\” style=\”max-width:100%”是让我们从手机选择的图片和网络加载的图片适配屏幕宽高,解决图片太大显示不全问题!

三、项目代码结构目录图

四、参考文章

richeditor-android github地址:https://github.com/wasabeef/richeditor-android

关于如何获得手机图片真正地址(realPathFromUri )请看:http://blog.csdn.net/huangxiaoguo1/article/details/78983582

移动端强大的富文本编辑器richeditor-android

代码地址如下:
http://www.demodashi.com/demo/14883.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

移动端强大的富文本编辑器richeditor-android的更多相关文章

  1. 富文本编辑器 - RichEditor

    基本功能 RichEditor 是一个继承自 WebView 的自己定义 view,枚举类型 Type 定了它所支持的排版格式: public enum Type { BOLD, ITALIC, SU ...

  2. 10个免费的javascript富文本编辑器(jQuery and non-jQuery)

    祝愿园子里的朋友圣诞节快乐. 本文介绍了10个免费易用富文本编辑器(rich text editors,RTE),其中5个是Jquery插件,另外5个是非Jquery富文本编辑器 简介 Javascr ...

  3. Vue集成tinymce富文本编辑器并实现本地化指南(2019.11.21最新)

     tinymce是一款综合口碑特别好.功能异常强大的富文本编辑器,在某些网站,甚至享有"宇宙最强富文本编辑器"的称号.那么,在Vue项目中如何集成呢?这并不困难,只需要参照官方教程 ...

  4. 现代富文本编辑器Quill的模块化机制

    DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...

  5. 现代富文本编辑器Quill的内容渲染机制

    DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...

  6. 移动端富文本编辑器artEditor

    摘要: 由于手机上打字比较慢,并不适合长篇大论的文章,所以移动端的富文本编辑器很少.artEditor是一款基于jQuery的移动端富文本编辑器,支持插入图片,后续完善其他功能. 插件地址:https ...

  7. quilljs 一款简单轻量的富文本编辑器(适合移动端)

    quilljs入门使用教程: quill.js是一款强大的现代富文本编辑器插件.该富文本编辑器插件支持所有的现代浏览器.平板电脑和手机.它提供了文本编辑器的所有功能,并为开发者提供大量的配置参数和方法 ...

  8. zx-editor 移动端(HTML5)富文本编辑器,可与原生App混合(hybrid)开发

    ZxEditor 移动端HTML文档(富文本)编辑器,支持图文混排.引用.大标题.无序列表,字体颜色.加粗.斜体. 可用于独立web项目开发,也可以用于与原生App混合(hybrid)开发. 源码地址 ...

  9. 关于移动手机端富文本编辑器qeditor图片上传改造

    日前项目需要在移动端增加富文本编辑,上网找了下,大多数都是针对pc版的,不太兼容手机,当然由于手机屏幕小等原因也限制富文本编辑器的众多强大功能,所以要找的编辑器功能必须是精简的. 找了好久,发现qed ...

随机推荐

  1. 接口隔离原则(Interface Segregation Principle,ISP)

    接口隔离原则: 1.使用多个专门的接口比使用单一的总接口要好. 2.一个类对另外一个类的依赖性应当是建立在最小的接口上的. 3.一个接口代表一个角色,不应当将不同的角色都交给一个接口.没有关系的接口合 ...

  2. 基于libnids的TCP数据流的还原(多线程实现) .

    我们知道,libnids本身可以实现TCP数据流的重组,但是如果一个TCP流数据量比较大的时候,就会分成好多个TCP报文段,这些报文段在网络中的传播可能是乱序的,利用libnids可以帮助我们按顺序接 ...

  3. 25个可遇不可求的jQuery插件

    随着jQuery插件在网站建设过程中的使用率不断的增加,所以有必要跟进时代步伐开发出一些新的插件/代码片段,以此来巩固并提高前端用户体验,将用户体验提升到一个新的高度. 接下来所推荐的这些插件中有滑块 ...

  4. 原生JS实现new方法、new一个对象发生的四部、new里面常用的优先级

    一.js中new一个对象的过程 首先了解new做了什么,使用new关键字调用函数(new ClassA(…))的具体步骤: 1.创建一个新对象: var obj = {}; 2.设置新对象的const ...

  5. TNTSearch 轻量级全文索引 + 中文分词

    TNTSearch 轻量级全文索引+中文分词 选用 TNTSearch 的原因:轻,方便移植,不需要额外安装服务,能减少后期维护的工作量.搜索的效果也还不错,可以满足大多数项目场景,如果对性能和精准度 ...

  6. 添加PMD插件扫描潜在的bug

    上一节使用checkstyle来规范你的项目主要解决了代码编码规范问题,比如缩进换行等.这次继续代码健康工具类PMD. 什么是PMD PMD真的不像checkstyle这样的东西所见即所得啊,去官网找 ...

  7. 如何实现Linux+Windows双系统启动

    设置你的计算机根据需要启动 Windows 10 或 Ubuntu 18.04. 尽管 Linux 是一个有着广泛的硬件和软件支持的操作系统,但事实上有时你仍需要使用 Windows,也许是因为有些不 ...

  8. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(八)安装zookeeper-3.4.12

    如何搭建配置centos虚拟机请参考<Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网.& ...

  9. 转:ffmpeg time_base详解

    ffmpeg time_base详解 https://my.oschina.net/u/3054677/blog/866368

  10. HttpWebRequest: Remote server returns error 503 Server Unavailable

      I have a client server application written in C# .Net 2.0. I have had the client/server response/r ...