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

Ser*_*sov 6 dart flutter

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

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

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

  • 段落
    使用“队列”来表示文本,而样式
    使用Canvas.drawParagraph(paragraph,offset)进行绘画

它们和使用哪个有什么区别?

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

Psy*_*hoX 24

tl;dr:imo TextPainter> Paragraph(因为更好的 API)。

我创建了简单的示例应用程序来比较在(of )上呈现文本的方法TextPainterParagraph方法。两种方法都很好,都使用不同的方法,都有奇怪的摆动。CanvasCustomPainter

TextPainter

起初我想提一下,TextPainter界面似乎更容易——至少对我来说。您只需要指定textTextSpanentry 或 tree 并且 - 奇怪的是,它不是默认的 - textDirection。您还可以提供诸如maxLines,styletextAlign(以及其他一些选项)之类的选项。然后您需要使用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));
Run Code Online (Sandbox Code Playgroud)

使用TextSpan在 Flutter 周围非常普遍 -RichText其他小部件也在使用这个类。我还必须注意到,使用TextPainter可以让你检查heightwidth文本像素的(渲染之前)。

Paragraph

第二:Paragraph。这似乎是更底层的、程序化的方法。正如您在下面看到的,Paragraph方法不太干净。首先你必须使用ParagraphBuilder(因为Paragraph没有构造函数)。你需要给它ParagraphStyle一个包含各种文本样式,如字体信息,textAlignmaxLines等等。然后您可以使用pushStyle,popaddText准备段落的下一部分和下一部分。build获得后Paragraph,您可以drawParagraph在您的Canvas.

        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));
Run Code Online (Sandbox Code Playgroud)

请注意,有两种类型TextStyle(Dart UI 和 Flutter)。与pushStyle您一致,可以看到Flutter 绘画库已TextStyle转换为Dart UITextStyle。另一个奇怪的事情是你可以/需要在ParagraphBuilder- 即使你要pushStyle在后面的行中使用一些字体设置。并且layout必须用 指定width

我认为我可以更好地用于读取文件等情况,尤其是在格式化时,因为不需要将文件解析为TextSpan树,这可能会很昂贵。如果您知道自己在做什么,我想它也可以比其他方法快一点,但我没有时间深入挖掘它。

最大行数问题

当文本过多时,您可能想要剪切文本。双方ParagraphTextPainter自曝maxLines-设置最大线-和didExceedMaxLines-检测限是否超出-在这种或那种方式。还有canvas.clipRect相关的方法可以将所有绘图剪辑到选定的空间中。

表现

还有一个简单的性能测试(在发布时),它表明两种方法是可比的(在我的测试案例TextPainter中比 快不超过 2% Paragraph)。也可能是测量误差¯\_(?)_/¯。