博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flutter 32: 图解 TextPainter 与 TextSpan 小尝试
阅读量:6794 次
发布时间:2019-06-26

本文共 8129 字,大约阅读时间需要 27 分钟。

      大家在学习 Flutter 时一定会用过 Text,而对于一些复杂文本的处理可能会选择 ,再进一步,使用 RichText 就一定要用 ,小菜本以为可以做为一个小知识点进行简单学习,但是随着深入尝试发现 TextSpan 涉及东西很多,很值得研究,因此单独整理一篇小博文。

      RichText 富文本核心即 TextSpan,而 TextSpan 结构很像 Android 中的 ViewGroup 树型结构。

TextSpan 树形结构.png

RichText 日常用法

      小菜理解为 RichText 是进阶版的 Text,如下直接看实例:

  1. TextDirection 用来控制文字位置,居左或居右边;当与 TextAlign 属性共存时,优先看整体,以 TextAlign 为准;
Widget richTextWid01() {  return RichText(      text: TextSpan(          text: 'TextDirection.ltr 文字默认居左',          style: TextStyle(fontSize: 16.0, color: Colors.black)),      textDirection: TextDirection.ltr);}Widget richTextWid02() {  return RichText(      text: TextSpan(          text: 'TextDirection.rtl 文字默认居右',          style: TextStyle(fontSize: 16.0, color: Colors.black)),      textDirection: TextDirection.rtl);}Widget richTextWid03() {  return RichText(      text: TextSpan(          text: 'textDirection 与 textAlign 同时设置,优先看整体,文字居中',          style: TextStyle(fontSize: 16.0, color: Colors.black)),      textDirection: TextDirection.rtl,      textAlign: TextAlign.center);}
  1. RichText 可以借助 TextSpan 实现文字的多种效果,小菜认为有点像文字效果拼接,每个 TextSpan 可以设置单独效果;
Widget richTextWid04() {  return RichText(      text: TextSpan(          text: '多种样式,如:',          style: TextStyle(fontSize: 16.0, color: Colors.black),          children: 
[ TextSpan( text: '红色', style: TextStyle(fontSize: 18.0, color: Colors.red)), TextSpan( text: '绿色', style: TextStyle(fontSize: 18.0, color: Colors.green)), TextSpan( text: '蓝色', style: TextStyle(fontSize: 18.0, color: Colors.blue)), TextSpan( text: '白色', style: TextStyle(fontSize: 18.0, color: Colors.white)), TextSpan( text: '紫色', style: TextStyle(fontSize: 18.0, color: Colors.purple)), TextSpan( text: '黑色', style: TextStyle(fontSize: 18.0, color: Colors.black)) ]), textAlign: TextAlign.center);}
  1. TextSpan 可以借助 recognizer 设置点击事件,包括点击/长按等;
final TapGestureRecognizer recognizer = TapGestureRecognizer();void initState() {  super.initState();  recognizer.onTap = () {    Toast.show('您好,欢迎点赞或关注!', context,        duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);  };}Widget richTextWid05() {  return RichText(      text: TextSpan(          text: 'recognizer 为手势识别者,可设置点击事件,',          style: TextStyle(fontSize: 17.0, color: Colors.black),          children: 
[ TextSpan( text: '点我试试', style: TextStyle(fontSize: 17.0, color: Colors.blue), recognizer: recognizer) ]));}

TextPainter 日常用法

      RichText 的使用很方便,但如果在深入了解 TextSpan 就有很多趣味了;Flutter 提供了和 Android 类似的 Canvas 绘制方法,但是 Canvas 却不支持 drawText,如果想要实现绘制文字,就需要 而其内部主要是由 TextSpan 实现。

      使用 TextPainter 时需要继承 CustomPainter,并实现 paintshouldRepaint 方法,主要是在 paint 中进行绘制 TextPainter。与 RichText 功能相同,可以完全实现 RichText 效果;

      TextPainter 绘制需要实现 layoutpaint 方法,即绘制位置与绘制范围。

  1. TextDirectionTextAlign 效果与 RichText 一致,但是 TextPainter 绘制时需要设置 layout 的最大最小范围,而此时,文字位置与 layout 有关;当文字长度小于设置的 minWidth 最小宽度时,以 minWidth 宽度为限制居左/居右/居中等;而当文字长度大于设置的 minWidth 最小宽度时,以 maxWidth 最大宽度为限制,包括换行等;
TextPainter(    text: TextSpan(        text: 'TextDirection.ltr 文字默认居左',        style: TextStyle(fontSize: 16.0, color: Colors.black)),    textDirection: TextDirection.ltr)  ..layout(maxWidth: Screen.width, minWidth: Screen.width)  ..paint(canvas, Offset(0.0, 0.0));TextPainter(    text: TextSpan(        text: 'TextDirection.rtl 文字默认居右',        style: TextStyle(fontSize: 16.0, color: Colors.black)),    textDirection: TextDirection.rtl)  ..layout(maxWidth: Screen.width, minWidth: Screen.width)  ..paint(canvas, Offset(0.0, 24.0));TextPainter(    text: TextSpan(        text: 'textDirection 与 textAlign 同时设置,优先看整体,文字居中',        style: TextStyle(fontSize: 16.0, color: Colors.black)),    textDirection: TextDirection.rtl,    textAlign: TextAlign.center)  ..layout(maxWidth: Screen.width, minWidth: Screen.width)  ..paint(canvas, Offset(0.0, 48.0));TextPainter(    text: TextSpan(        text: '文字位置与 layout 的最大最小宽度有关',        style: TextStyle(fontSize: 16.0, color: Colors.black)),    textDirection: TextDirection.rtl)  ..layout(maxWidth: Screen.width - 100.0, minWidth: Screen.width - 200.0)  ..paint(canvas, Offset(0.0, 90.0));TextPainter(    text: TextSpan(        text: '文字长度较小',        style: TextStyle(fontSize: 16.0, color: Colors.black)),    textDirection: TextDirection.rtl)  ..layout(maxWidth: Screen.width - 100.0, minWidth: Screen.width - 140.0)  ..paint(canvas, Offset(0.0, 124.0));
  1. 而对于绘制多效果的样式也是很方便,与 RichText 基本一致;
TextPainter(    text: TextSpan(        text: '多种样式,如:',        style: TextStyle(fontSize: 16.0, color: Colors.black),        children: 
[ TextSpan( text: '红色', style: TextStyle(fontSize: 18.0, color: Colors.red)), TextSpan( text: '绿色', style: TextStyle(fontSize: 18.0, color: Colors.green)), TextSpan( text: '蓝色', style: TextStyle(fontSize: 18.0, color: Colors.blue)), TextSpan( text: '白色', style: TextStyle(fontSize: 18.0, color: Colors.white)), TextSpan( text: '\n紫色', style: TextStyle(fontSize: 18.0, color: Colors.purple)), TextSpan( text: '黑色', style: TextStyle(fontSize: 18.0, color: Colors.black)) ]), textDirection: TextDirection.ltr, textAlign: TextAlign.center) ..layout(maxWidth: Screen.width, minWidth: Screen.width) ..paint(canvas, Offset(0.0, 148.0));
  1. 小菜一直有问题的就是设置点击事件,小菜以为与 RichText 一样直接传递 recognizer 即可,但始终无法调起,希望有解决过这个问题的朋友多多指导,如下是小菜的测试代码;
TextPainter(    text: TextSpan(        text: 'recognizer 为手势识别者,可设置点击事件,',        style: TextStyle(fontSize: 17.0, color: Colors.black),        children: 
[ TextSpan( text: '测试暂时有误,待研究', style: TextStyle(fontSize: 17.0, color: Colors.blue)) ], recognizer: TapGestureRecognizer() ..onTap = () { print('===测试暂时有误,待研究=='); }), textDirection: TextDirection.ltr, textAlign: TextAlign.center) ..layout(maxWidth: Screen.width - 40.0, minWidth: Screen.width - 40.0) ..paint(canvas, Offset(20.0, 200.0));
  1. 小菜认为最有意思的就是 TextSpanstyleheight 属性,在 TextSpan 中此值设置行高,是以文字基准线为最小距离;
TextPainter(    text: TextSpan(        text: 'TextPainter 小尝试',        style: TextStyle(fontSize: 20.0, color: Colors.black54),        children: 
[ TextSpan( text: '\n作者:和尚(height:1.6)', style: TextStyle( fontSize: 14.0, color: Colors.black54, height: 1.6)) ]), textDirection: TextDirection.ltr, textAlign: TextAlign.center) ..layout(maxWidth: Screen.width, minWidth: Screen.width) ..paint(canvas, Offset(0.0, 20.0));TextPainter( text: TextSpan( text: 'TextPainter 小尝试', style: TextStyle(fontSize: 20.0, color: Colors.black54), children:
[ TextSpan( text: '\n作者:和尚(height:3.0)', style: TextStyle( fontSize: 14.0, color: Colors.black54, height: 3.0)) ]), textDirection: TextDirection.ltr, textAlign: TextAlign.center) ..layout(maxWidth: Screen.width, minWidth: Screen.width) ..paint(canvas, Offset(0.0, 90.0));TextPainter( text: TextSpan( text: 'TextPainter 小尝试(height:0.1)', style: TextStyle(fontSize: 20.0, color: Colors.black54, height: 0.1), children:
[ TextSpan( text: '\nTextPainter 小尝试(height:0.1)', style: TextStyle( fontSize: 20.0, color: Colors.black54, height: 0.1)), TextSpan( text: '\nTextPainter 小尝试(height:0.1)', style: TextStyle( fontSize: 20.0, color: Colors.black54, height: 0.1)) ]), textDirection: TextDirection.ltr, textAlign: TextAlign.center) ..layout(maxWidth: Screen.width, minWidth: Screen.width) ..paint(canvas, Offset(0.0, 220.0));


      如果有不对的地方还希望多多指教!

转载地址:http://fmrgo.baihongyu.com/

你可能感兴趣的文章
mac下mysql忘记root密码
查看>>
谈谈浏览器的缓存过期时间
查看>>
secilog 1.15 发布,增加数据库采集网站访问统计
查看>>
secilog 1.17 发布 增加了英文版本等新功能
查看>>
四城记之哈尔滨
查看>>
django模版过滤器
查看>>
2015年10月19日作业
查看>>
Skia深入分析10——Skia库的性能与优化潜力
查看>>
PYTHON 文件操作
查看>>
Python---生成器
查看>>
centos7上部署oVirt平台管理kvm
查看>>
网络存储 前序(存储基础) --iscsi
查看>>
mysql数据库
查看>>
mysql 存储过程的创建
查看>>
安卓学习UI组件-PopupWindow-弹出窗口
查看>>
thinkphp的M方法小结
查看>>
js在页面中嵌入pdf文件
查看>>
LVM磁盘扩容流程
查看>>
LogMiner的使用
查看>>
MySQL索引失效及使用索引的优缺点
查看>>