Flutter-TextPainer与用于绘图书页的段落

时间:2018-08-01 18:49:51

标签: dart flutter

我需要显示长文本,它将占据多个屏幕/页面。我还必须添加一些功能,因此我想实现自己的文本显示组件。

我发现了两个与此任务相对应的类:

  • TextPainter
    TextSpan 用于文本
    使用 paint(canvas,offset)绘画

  • 段落
    为文字和样式使用“队列”
    使用 Canvas.drawParagraph(paragraph,offset)绘画

它们和要使用的是什么?!

如果文本包含100行,并且页面上只能放置10行,那么如何在下一页上绘制被截断的文本,直到没有剩余?

1 个答案:

答案 0 :(得分:0)

tl; dr:imo TextPainter> Paragraph(由于API更好)。

我创建了simple example app,以比较TextPainterParagraphCustomPainter的{​​{3}}上呈现文本的方法。两种方法都非常好,都使用了不同的方法,都存在奇怪的摆动。

TextPainter

首先,我想提一下TextPainter界面似乎更容易-至少对我而言。您只需要指定text作为Canvas条目或树,并且-很奇怪,这不是默认设置-textDirection。您还可以提供诸如maxLinesstyletextAlign等选项。然后,您需要使用layout来指定渲染的放置方式(仅maxWidth)。最后,在指定的paint上某些Canvas上的Offset

        final TextPainter textPainter = TextPainter(
          text: TextSpan(text: text, style: style),
          textAlign: TextAlign.justify,
          textDirection: TextDirection.ltr
        )
          ..layout(maxWidth: size.width - 12.0 - 12.0);  
        textPainter.paint(canvas, const Offset(12.0, 36.0));

使用过的TextSpan在Flutter上非常普遍-RichText和其他小部件也在使用此类。我还必须注意,使用 TextPainter可以检查heightwidth以像素为单位的文本(在渲染之前)。

Paragraph

第二:Paragraph。这似乎是更基础的程序方法。如下所示,Paragraph方法不太干净。首先,您必须使用ParagraphBuilder(因为Paragraph没有构造函数)。您需要用TextSpan来填充它,其中包含各种文本样式,例如字体信息,textAlignmaxLines等。然后,您可以使用pushStylepopaddText准备该段落的下一部分和下一部分。 build之后,您将获得Paragraph,您可以在drawParagraphCanvas

        final ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(
          ui.ParagraphStyle(
            fontSize:   style.fontSize,
            fontFamily: style.fontFamily, 
            fontStyle:  style.fontStyle,
            fontWeight: style.fontWeight,
            textAlign: TextAlign.justify,
          )
        )
          ..pushStyle(style.getTextStyle())
          ..addText(text);
        final ui.Paragraph paragraph = paragraphBuilder.build()
          ..layout(ui.ParagraphConstraints(width: size.width - 12.0 - 12.0)); 
        canvas.drawParagraph(paragraph, const Offset(12.0, 36.0));

请注意,TextStyle有两种类型(Dart UI和Flutter)。与pushStyle一致,您可以看到ParagraphStyle被转换为Flutter Painting library TextStyle。另一个奇怪的事情是,即使您将在后面的行中使用ParagraphBuilder,也可以仅在pushStyle中指定一些字体设置。并且layout必须用width指定。

我认为在读取文件(尤其是格式化文件)的情况下,我会更好,因为不需要将文件解析为TextSpan树,这可能会很昂贵。我想如果您知道自己在做什么,它的速度也可能比其他方法快一点,但是我没有时间对此进行深入研究。

最大行数问题

当文本过多时,您可能希望将其剪切。 ParagraphTextPainter都以一种或另一种方式公开maxLines-设置最大行数和didExceedMaxLines-以检测是否超出了限制。还有canvas.clipRect和相关方法,可以将所有图形剪切到选定的空间中。

性能

还有一个简单的Dart UI TextStyle(发布时),表明这两种方法是可比的(在我的测试案例中,TextPainterParagraph快2%)。可能也是测量误差¯\ _(ツ)_ /¯。