Flutter-绘图书页面的TextPainter vs Paragraph [英] Flutter - TextPainter vs Paragraph for drawing book page

查看:129
本文介绍了Flutter-绘图书页面的TextPainter vs Paragraph的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to display long text, which will occupy several screens/pages. I have to add some features also, so I would like to implement my own text displaying component.

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

I found two classes that corresponds to this task:

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

段落
使用队列"为他们的文字和样式
使用 Canvas.drawParagraph(paragraph,offset)绘画

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

What is the difference between them and which one to use?!

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

If the text contains 100 lines and only 10 lines can be placed on a page, then how to draw truncated text on the next pages until nothing left?

推荐答案

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

tl;dr: imo TextPainter > Paragraph (because of better API).

我创建了简单的示例应用,以比较两个

I created simple example app to compare both TextPainter and Paragraph methods of rendering text on Canvas (of CustomPainter). Both methods are pretty good, both uses different approaches, both have their weird wobbles.

首先,我想提一下 TextPainter 界面似乎更容易-至少对我来说.您只需要将 text 指定为 TextSpan 条目或树,-奇怪的是,它不是默认值- textDirection .您还可以提供诸如 maxLines style textAlign 之类的选项(以及其他几个选项).然后,您需要使用 layout 来指定渲染的放置方式(当然,仅 maxWidth ).最后,在指定的 Offset 上的某些 Canvas paint .

At first I want to mention that TextPainter interface seems to be easier - at least for me. You just need to specify text as TextSpan entry or tree and - what is weird, it isn't default - textDirection. You can also provide options such as maxLines, style and textAlign (and few others). Then you need to use layout to specify how the rendering would be laying (well, maxWidth only). And finally, paint on certain Canvas at specified 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 允许您以像素为单位检查文本的 height width (在渲染之前)

Used TextSpan is quite universal around the Flutter - RichText and other widgets also are using this class. I also must notice that using TextPainter allows you to check height and width of text in pixels (before rendering).

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

Second: Paragraph. This seems to be more underlying, procedural method. As you can see below, Paragraph method is less cleaner. First you must use ParagraphBuilder (since Paragraph have no constructor). You need to feed it with ParagraphStyle that contains various text styling such as font information, textAlign, maxLines and so on. Then you can use pushStyle, pop and addText to prepare next and next portion of the paragraph. After build you get the Paragraph which you can drawParagraph on your 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));

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

Be aware, there is two types of TextStyle (Dart UI and Flutter). In line with pushStyle you can see that Flutter Painting library TextStyle got transformed into Dart UI TextStyle. Another weird thing is that you can/need specify few font settings just in the ParagraphBuilder - even though you are going to use pushStyle in the line after. And the layout must be specified with width.

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

I think I could be better to use in situations like reading file, especially with formatting, since there will be no need to parse the file into TextSpan tree, which could be costly. I suppose it can be also a bit faster than other methods if you are know what you are doing, but I do not have time to dig it that deeply.

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

You might want to clip the text when there is too much of it. Both Paragraph and TextPainter exposes maxLines - to set max lines - and didExceedMaxLines - to detect whether the limit was exceeded -, in one way or another. There is also canvas.clipRect and related methods which allows to clip all drawing into selected space.

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

There is also simple performance test (on release), which shows that both methods are comparable (in my testing case TextPainter was no more than 2% faster than Paragraph). It might be also measurement error ¯\_(ツ)_/¯.

这篇关于Flutter-绘图书页面的TextPainter vs Paragraph的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆