Flutter-绘图书页面的TextPainter vs Paragraph [英] Flutter - TextPainter vs Paragraph for drawing book page
问题描述
我需要显示长文本,它将占据多个屏幕/页面.我还必须添加一些功能,因此我想实现自己的文本显示组件.
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屋!