YCCustomText

Introduction: 自定义文本控件,支持富文本,包含两种状态:编辑状态和预览状态。编辑状态中,可以对插入本地或者网络图片,可以同时插入多张有序图片和删除图片,支持图文混排,并且可以对文字内容简单操作加粗字体,设置字体下划线,支持设置文字超链接(超链接支持跳转),功能正在开发中和完善中……
More: Author   ReportBugs   
Tags:

目录介绍

  • 01.富文本控件介绍
  • 02.业务需求简单介绍
  • 03.富文本支持功能
  • 04.富文本实现方案
  • 05.富文本如何使用
  • 06.富文本开发步骤
  • 07.富文本遗留问题
  • 08.其他说明介绍

01.富文本控件介绍

1.1 富文本介绍

  • 自定义文本控件,支持富文本,包含两种状态:编辑状态和预览状态。编辑状态中,可以对插入本地或者网络图片,可以同时插入多张有序图片和删除图片,支持图文混排,并且可以对文字内容简单操作加粗字体,设置字体下划线,支持设置文字超链接(超链接支持跳转),支持字数和图片数量统计,功能正在开发中和完善中……

1.2 富文本截图

image image image image image image

02.业务需求简单介绍

  • 富文本控件支持动态插入文字,图片等图文混排内容。图片可以支持本地图片,也支持插入网络链接图片;
  • 富文本又两种状态:编辑状态 + 预览状态 。两种状态可以相互进行切换;
  • 富文本在编辑状态,可以同时选择插入超过一张以上的多张图片,并且可以动态设置图片之间的 top 间距;
  • 在编辑状态,支持利用光标删除文字内容,同时也支持用光标删除图片;
  • 在编辑状态,插入图片后,图片的宽度填充满手机屏幕的宽度,然后高度可以动态设置,图片是剧中裁剪显示;
  • 在编辑状态,插入图片后,如果本地图片过大,要求对图片进行质量压缩,大小压缩;
  • 在编辑状态,插入多张图片时,添加插入过渡动画,避免显示图片生硬。结束后,光标移到插入图片中的最后一行显示;
  • 编辑状态中,图片点击暴露点击事件接口,可以在 4 个边角位置动态设置一个删除图片的功能,点击删除按钮则删除图片;
  • 连续插入多张图片时,比如顺序 1,2,3,注意避免出现图片插入顺序混乱的问题(异步插入多张图片可能出现顺序错乱问题);
  • 在编辑富文本状态的时候,连续多张图片之间插入输入框,方便在图片间输入文本内容;
  • 在编辑状态中,可以设置文字大小和颜色,同时做好拓展需求,后期可能添加文本加粗,下划线,插入超链接,对齐方式等功能;
  • 编辑状态,连续插入多张图片,如果想在图片中间插入文字内容,则需要靠谱在图片之间预留编辑文本控件,方便操作;
  • 支持对文字选中的内容进行设置加粗,添加下划线,改变颜色,设置对齐方式等等;
  • 多线程环境下,富文本编辑状态插入图片或者文字控件使用了同步锁。针对 lib,方法访问权限不可滥用;
  • 充分使用了面向对象的编程思想,低耦合,易维护,便于拓展,不断更新维护该富文本库;
  • 富文本中支持动态设置输入文本光标的颜色,使用反射修改属性;

03.富文本支持功能

  • 支持加粗、斜体、删除线、下划线行内样式,一行代码即可设置文本 span 属性,十分方便
  • 支持添加单张或者多张图片,并且插入过渡动画友好,同时可以保证插入图片顺序
  • 支持富文本编辑状态和预览状态的切换,支持富文本内容转化为 json 内容输出,转化为 html 内容输出
  • 支持设置富文本的文字大小,行间距,图片和文本间距,以及插入图片的宽和高的属性
  • 图片支持点击预览,支持点击叉号控件去除图片,暴露给外部开发者调用。同时加载图片的逻辑也是暴露给外部开发者,充分解耦
  • 关于富文本字数统计,由于富文本中包括文字和图片,因此图片和文字数量统计分开。参考易车是:共 n 个文字,共 n 个图片显示
  • 富文本中支持动态设置图片的宽高适应条件,比如高度在 100 到 200dp 之间,支持动态设置删除按钮的位置

04.富文本实现方案

4.0 页面构成分析

  • 整个界面的要求
    • 整体界面可滚动,可以编辑,也可以预览
    • 内容可编辑可以插入文字、图片等。图片提供按钮操作
    • 软键盘删除键可删除图片,也可以删除文字内容
    • 文字可以修改属性,比如加粗,对齐,下划线
  • 根据富文本作出以下分析
    • 使用原生控件,可插入图片、文字界面不能用一个 EditText 来做,需要使用 LinearLayout 添加不同的控件,图片部分用 ImageView,界面可滑动最外层使用 ScrollView。
    • 使用 WebView+js+css 方式,富文本格式用 html 方式展现,比较复杂,对标签要非常熟悉才可以尝试使用
  • 使用原生控件多焦点问题分析
    • 界面是由多个输入区域拼接而成,暂且把输入区域称为 EditText,图片区域称为 ImageView,外层是 LinearLayout。
    • 如果一个富文本是:文字 1+图片 1+文字 2+文字 3+图片 3+图片 4;那么使用 LinearLayout 包含多个 EditText 实现的难点:
      • 如何处理记录当前的焦点区域
      • 如何处理在文字区域的中间位置插入 ImageView 样式的拆分和合并
      • 如何处理输入区域的删除键处理

4.1 第一种方案

  • 使用 ScrollView 作为最外层,布局包含 LineaLayout,图文混排内容,则是用 TextView/EditText 和 ImageView 去填充。
  • 富文本编辑状态:ScrollView + LineaLayout + n 个 EditText+Span + n 个 ImageView
  • 富文本预览状态:ScrollView + LineaLayout + n 个 TextView+Span + n 个 ImageView
  • 删除的时候,根据光标的位置,如果光标遇到是图片,则可以用光标删除图片;如果光标遇到是文字,则可以用光标删除文字
  • 当插入或者删除图片的时候,可以添加一个过渡动画效果,避免直接生硬的显示。如何在 ViewGroup 中添加 view,删除 view 时给相应 view 和受影响的其他 view 添加动画,不太容易做。如果只是对受到影响的 view 添加动画,可以通过设置 view 的高度使之显示和隐藏,还可以利用 ScrollView 通过滚动隐藏和显示动画,但其他受影响的 view 则比较难处理,最终选择布局动画 LayoutTransition 就可以很好地完成这个功能。

4.2 第二种方法

  • 使用 WebView 实现编辑器,支持 n 多格式,例如常见的 html 或者 markdown 格式。利用 html 标签对富文本处理,这种方式就需要专门处理标签的样式。
  • 注意这种方法的实现,需要深入研究 js,css 等,必须非常熟悉才可以用到实际开发中,可以当作学习一下。这种方式对于图片的显示和上传,相比原生要麻烦一些。

05.富文本如何使用

  • 如何引用
      implementation 'cn.yc:YCCustomTextLib:2.1.3'
    
  • 在布局中引用,HyperTextEditor 是编辑富文本,HyperTextView 是预览富文本 ``` <?xml version="1.0" encoding="utf-8"?>

      <com.ns.yc.yccustomtextlib.edit.view.HyperTextEditor
          android:id="@+id/hte_content"
          android:visibility="visible"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@android:color/white"
          android:textSize="16sp"
          app:editor_text_line_space="6dp"
          app:editor_image_height="500"
          app:editor_image_bottom="10"
          app:editor_text_init_hint="在这里输入内容"
          app:editor_text_size="16sp"
          app:editor_text_color="@android:color/black"/>
    
    <com.ns.yc.yccustomtextlib.edit.view.HyperTextView
        android:id="@+id/htv_content"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:ht_view_text_line_space="6dp"
        app:ht_view_image_height="0"
        app:ht_view_image_bottom="10"
        app:ht_view_text_size="16sp"
        app:ht_view_text_color="@android:color/black"/>

</LinearLayout>
```
  • 在编辑富文本状态时,HyperTextEditor 控件

      //插入图片
      hte_content.insertImage(imagePath);
      //对外提供的接口, 生成编辑数据上传
      List<HyperEditData> editList = hte_content.buildEditData();
    
      hte_content.setOnHyperListener(new OnHyperEditListener() {
          @Override
          public void onImageClick(View view, String imagePath) {
              //图片点击事件
              ToastUtils.showRoundRectToast("图片点击"+imagePath);
          }
    
          @Override
          public void onRtImageDelete(String imagePath) {
              //图片删除成功事件
              ToastUtils.showRoundRectToast("图片删除成功");
          }
    
          @Override
          public void onImageCloseClick(final View view) {
              //图片删除图片点击事件
          }
      });
      hte_content.setOnHyperChangeListener(new OnHyperChangeListener() {
          @Override
          public void onImageClick(int contentLength, int imageLength) {
              //富文本的文字数量,图片数量统计
              tv_length.setText("文字共"+contentLength+"个字,图片共"+imageLength+"张");
          }
      });
    
  • 在预览富文本状态时,HyperTextView 控件

      //清除所有文本
      htv_content.clearAllLayout();
      //将 html 数据转化成集合
      List<String> textList = HyperLibUtils.cutStringByImgTag(html);
      //省略部分代码,具体看 demo
      if (text.contains("<img") && text.contains("src=")) {
          //imagePath 可能是本地路径,也可能是网络地址
          String imagePath = HyperLibUtils.getImgSrc(text);
          //在特定位置添加 ImageView
          htv_content.addImageViewAtIndex(htv_content.getLastIndex(), imagePath);
      } else {
          //在特定位置插入 TextView
          htv_content.addTextViewAtIndex(htv_content.getLastIndex(), text);
      }
    
      htv_content.setOnHyperTextListener(new OnHyperTextListener() {
          @Override
          public void onImageClick(View view, String imagePath) {
              //图片点击事件
          }
      });
    
  • 关于 HyperTextEditor 的属性介绍说明
      <declare-styleable name="HyperTextEditor" >
          <!--父控件的左和右 padding-->
          <attr name="editor_layout_right_left" format="integer" />
          <!--父控件的上和下 padding-->
          <attr name="editor_layout_top_bottom" format="integer" />
          <!--插入的图片显示高度-->
          <attr name="editor_image_height" format="integer" />
          <!--两张相邻图片间距-->
          <attr name="editor_image_bottom" format="integer" />
          <!--文字相关属性,初始提示信息-->
          <attr name="editor_text_init_hint" format="string" />
          <!--文字大小-->
          <attr name="editor_text_size" format="dimension" />
          <!--文字颜色-->
          <attr name="editor_text_color" format="color" />
          <!--文字行间距-->
          <attr name="editor_text_line_space" format="dimension" />
          <!--删除图片图标的位置-->
          <attr name="editor_del_icon_location" format="enum">
              <enum name="top_left" value="1" />
              <enum name="top_right" value="2" />
              <enum name="bottom_left" value="3" />
              <enum name="bottom_right" value="4" />
          </attr>
      </declare-styleable>
    

06.富文本开发步骤

  • 01.业务需求简单介绍
  • 02.实现的方案介绍
  • 03.异常状态下保存状态信息
  • 04.处理软键盘回删按钮逻辑
  • 05.在指定位置插入图片
  • 06.在指定位置插入输入文字
  • 07.如果对选中文字加粗
  • 08.利用 Span 对文字属性处理
  • 09.如何设置插入多张图片
  • 10.如何设置插入网络图片
  • 11.如何避免插入图片 OOM
  • 12.如何删除图片或者文字
  • 13.删除和插入图片添加动画
  • 14.点击图片可以查看大图
  • 15.如何暴露设置文字属性方法
  • 16.文字中间添加图片注意事项
  • 17.键盘弹出和收缩优化
  • 18.前后台切换编辑富文本优化
  • 19.合理运用面向对象编程思想
  • 20.用的设计模式介绍
  • 21.生成 html 片段上传服务器
  • 22.生成 json 片段上传服务器
  • 23.图片上传策略问题思考
  • 24.合理运用面向对象编程思想
  • 25.如何代码修改输入光标颜色
  • 更多信息

07.富文本遗留问题

  • 01.业务要求插入单个图片最高 200,最小高度 100
  • 02.根据手机屏幕按照比例进行展示图片宽高
  • 03.在富文本编辑页面携带数据传递到下一个页面注意点
  • 更多信息

08.其他说明介绍

参考博客和开源项目

关于其他内容介绍

image

关于博客汇总链接

其他推荐

  • 博客笔记大汇总【15 年 10 月到至今】,包括 Java 基础及深入知识点,Android 技术博客,Python 学习笔记等等,还包括平时开发中遇到的 bug 汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是 markdown 格式的!同时也开源了生活博客,从 12 年起,积累共计 47 篇[近 100 万字],转载请注明出处,谢谢!
  • 链接地址:https://github.com/yangchong211/YCBlogs
  • 如果觉得好,可以 star 一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!

关于 LICENSE

Copyright 2017 yangchong211(github.com/yangchong211)

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.
Apps
About Me
GitHub: Trinea
Facebook: Dev Tools