写点什么

【Flutter 专题】115 图解自定义 View 之 Canvas (四) drawParagraph

发布于: 2021 年 06 月 02 日
【Flutter 专题】115 图解自定义 View 之 Canvas (四) drawParagraph

    小菜在前两节通过 Canvas 绘制图形时涉及到部分文字绘制,之前只是简单的尝试,有很多未注意到的地方;小菜今天尝试全面的学习尝试一下;通过 Canvas 绘制文字时使用的属性效果与直接使用 TextView 对应基本一致;

Canvas.drawParagraph

  1. 新建一个 ParagraphBuilder 段落构造器;

  2. 在构造器中添加文本的基本信息,包括 ParagraphStyle 文本属性等;

  3. 通过 ParagraphConstraints 约束段落容器宽度;

  4. 通过 layout 计算段落中每个字形的大小和位置;

  5. 通过 Canvas.drawParagraph 进行文字绘制;


// 1-2 段落构造器并添加文本信息ParagraphBuilder _pb = ParagraphBuilder(    ParagraphStyle(fontWeight: FontWeight.normal, fontSize: 17))  ..pushStyle(ui.TextStyle(color: Colors.blue))  ..addText(str);// 3 设置段落容器宽度ParagraphConstraints pc = ParagraphConstraints(width: size.width - 100);// 4 计算文本位置及尺寸Paragraph paragraph = _pb.build()..layout(pc);// 5 文本绘制canvas.drawParagraph(paragraph, Offset(50.0, 50.0));
复制代码

ParagraphStyle

1. fontSize

    fontSize 为字体绘制时字号,以逻辑像素为单位;


fontSize: 14.0 + (i + 1)
复制代码



2. fontWeight

    fontWeight 用于绘制文本的字形的粗细,从 w100 -> w900 逐级变粗;默认是 w400


fontWeight: FontWeight.values[i + 1],
复制代码



3. fontStyle

    fontStyle 为字体样式,是否为 normal 正规或 italic 斜体;


fontStyle: (i % 2 == 0) ? FontStyle.normal : FontStyle.italic,
复制代码



4. fontFamily

    fontFamily 为文字的字体,使用其他字体时需要倒入字体包资源文件并在 pubspec.yaml 中进行资源文件注册声明;可以从 Google Fonts 字体库中选择适当的字体类型;


fontFamily: 'DancingScript',// pubspec.yamlflutter:  fonts:    - family: DancingScript      fonts:        - asset: images/DancingScript-Regular.ttf
复制代码



    小菜在添加字体时,遇到 A dependency specification must be a string or a mapping. 问题,其原因是字体资源的注册需要在 flutter: 中添加,而不是在 dependencies: 依赖中添加,dependencies: 都是添加的依赖键值对;



5. maxLines & ellipsis

    maxLines 为段落最长绘制行数,一般与 ellipsis 通过使用,ellipsis 为最后绘制不完时展示的文本内容;


maxLines: 4,ellipsis: '...',
复制代码



6. textDirection & textAlign

    textDirection & textAlign 的使用是小菜觉得应当注意的地方;textDirection 为文字绘制方向,ltrleft-to-right 从左至右;rtlright-to-left 从右至左,类似于 'ar/fa/he/ps/ur' 阿拉伯语和希伯来语等;textAlign 为文本的对齐方式;


    使用 rtl 方式时,标点均会展示在左侧,符合从右向左的绘制顺序;TextAlign 对齐方式注意区分 left / startright / end 的不同;


  • TextAlign.center 文本内容居中

  • TextAlign.justifyTextDirection 设置为准,自动延展填充至容器宽度

  • TextAlign.left 均与容器左侧对齐

  • TextAlign.startTextDirection 设置为准,开始位置进行对齐

  • TextAlign.right 均与容器右侧对齐

  • TextAlign.endTextDirection 设置为准,结束位置进行对齐


textAlign: _paragraphTextAlign(i),textDirection: (i % 2 == 0) ? TextDirection.ltr : TextDirection.rtl,
// TextAlign & TextDirectionenum TextAlign { left, right, center, justify, start, end, }enum TextDirection { ltr, rtl }
复制代码



7. height

    height 简单理解为行高,但并非完全与 fontSize 倍数一致;


height: 2,
复制代码



8. strutStyle

    strutStyle 小菜理解为段落高度属性,通过设置一系列垂直方向的维度定义更高级的行高属性;其中 StrutStyle 设置的 fontSize / fontFamily 等都是以此为基准线,借此改变的是段落行高,而不会改变段落文本属性(字号/字体等);


ParagraphBuilder _pb = ParagraphBuilder(ParagraphStyle(  height: 2, fontSize: 17,  strutStyle: ui.StrutStyle(fontFamily: 'DancingScript', fontSize: 20, height: 2),))
复制代码



ParagraphBuilder

1. pushStyle()

    pushStyle() 将给定的 TextStyle 样式添加到文本属性中,包括文字的颜色,背景等一系列样式;


    TextStyle 中涉及多种文本样式,对于与 ParagraphStyle 段落属性相同的 fontSize / fontFamily 等,以 TextStyle 为准;其中对于文本颜色,color 不能与 foreground 一同使用;wordSpacing 为单词间隔,letterSpacing 为文字字母之间间隔,两者要有区分;


var _gradient = ui.Gradient.linear(    Offset(0.0, 0.0),    Offset(0.0, size.height),    [Colors.orange, Colors.deepOrange, Colors.green],    [0 / 3, 1 / 3, 2 / 3]);var _bgGradient = ui.Gradient.linear(    Offset(0.0, 0.0),    Offset(0.0, size.height),    [Colors.blueGrey, Colors.white, Colors.grey],    [0 / 3, 1 / 3, 2 / 3]);var _shadow = [  Shadow(offset: Offset(2.0, 2.0), blurRadius: 4.0, color: Colors.grey)];ParagraphBuilder _pb = ParagraphBuilder(ParagraphStyle(fontSize: 17))  ..pushStyle(ui.TextStyle(      // color: Colors.green,      foreground: Paint()..shader = _gradient,      // background: Paint()..shader = _bgGradient,      fontSize: 20,      fontWeight: FontWeight.w700,      wordSpacing: 4,      letterSpacing: 2,      shadows: _shadow))  ..addText(str);ParagraphConstraints pc = ParagraphConstraints(width: size.width - 100);Paragraph paragraph = _pb.build()..layout(pc);canvas.drawParagraph(paragraph, Offset(50.0, 50 + _spaceHeight));
复制代码



2. addText()

    addText() 将给定的文本添加到段落中,并以设置好的段落样式进行绘制;

3. addPlaceholder()

    addPlaceholder() 为文字绘制中设置占位区域;若在 addText() 之前设置优先展示占位区域在进行文本绘制,若在之后设置则是文本绘制结束后添加占位;且有多种垂直占位对齐方式;


for (int i = 0; i < 3; i++) {  ParagraphBuilder _pb = ParagraphBuilder(ParagraphStyle(fontSize: 18))    ..pushStyle(ui.TextStyle(        foreground: Paint()..shader = _gradient,        fontWeight: FontWeight.w700, wordSpacing: 4));  if (i == 0) {    _pb = _pb..addPlaceholder(60, 60, i <= 1 ? PlaceholderAlignment.bottom : PlaceholderAlignment.middle);    _pb = _pb..addText(str);  } else {    _pb = _pb..addText(str);    _pb = _pb..addPlaceholder(60, 60, i <= 1 ? PlaceholderAlignment.bottom : PlaceholderAlignment.middle);  }  ParagraphConstraints pc = ParagraphConstraints(width: size.width - 100);  Paragraph paragraph = _pb.build()..layout(pc);  canvas.drawParagraph(paragraph, Offset(50.0, 50 + _spaceHeight));  canvas.drawRect(      Rect.fromPoints(Offset(49.0, 50.0 + _spaceHeight),          Offset(size.width - 49, 50.0 + paragraph.height + _spaceHeight)),      _paint..shader = _gradient);  _spaceHeight += paragraph.height;}
复制代码



    小菜对于 Canvas.drawParagraph 的尝试暂时到目前为止,还有很多特有属性会在实际过程中进行研究尝试;如有错误,请多多指导!




    Canvas.drawParagraph 案例源码




来源: 阿策小和尚

发布于: 2021 年 06 月 02 日阅读数: 7
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
【Flutter 专题】115 图解自定义 View 之 Canvas (四) drawParagraph