老孟导读:此文翻译自:https://medium.com/@suragch/m...
我喜爱Flutter。我喜爱开发一次并让代码在Android和iOS上运行。我喜爱节俭多少工夫。我喜爱当初成为一名Web开发人员,而无需做任何额定的工作。我喜爱hot reload。我喜爱通过将小部件组合到布局中来疾速构建UI。我喜爱制作ListView简略得多。我喜爱状态治理。 (好吧,只是在开玩笑。然而我能够应酬。)我喜爱Dart。我喜爱Future和async / await比Android AsyncTasks甚至iOS Dispatch Queue容易得多。
然而,在花了最初两周的工夫钻研Flutter如何出现文本后,我对应用的工具感到悲观。
咱们被告知:
Flutter的分层体系结构使您能够管制屏幕上的每个像素。
这显然不适用于用于绘制文本的像素。
Flutter中的低级文字性能
Flutter应用名为LibTxt的库联合应用Skia,Hafbuzz,Minikin和ICU来出现文本。开发人员在应用Text小部件或TextSpan甚至是TextPainter工夫接应用它。在最低级别上,咱们能够应用dart:iu,它是应用ParagraphBuilder构建的Paragraph类。这些类基本上只是底层LibTxt引擎的包装器。简直所有工作都由此引擎实现,而在dart:ui中简直没有裸露。
Paragraph类为咱们提供了以下管制:
- Size:我能够获取整个渲染段落的宽度和高度,它能够是单行或多行。
- 距基线的间隔(仅对于第一行)
- 文本是否溢出了maxLines变量。
- 文本框的大小和绝对地位。这是一个例子:
- 最靠近某个像素地位的文本字符索引。在下面的示例中,像素(1、1)对应于字符串中的索引0,即“My text line.”的字母“ M”。
- 字符串中某些字符偏移的单词边界。
随后的更新也为咱们提供了LineMetrics,它为每行提供了许多详细信息:
class LineMetrics { final bool hardBreak; final double ascent; final double descent; final double unscaledAscent; final double height; final double width; final double left; final double baseline; final int lineNumber;}
然而,咱们没有失去:
- 一种在文本框中获取理论文本的办法。
- 一种管制文本布局形式的办法。
- 一种在门路上绘制文本的办法。
- 一种无需绘制整个段落即可测量和绘制短文本的办法。
- 一种从文本字符串获取换行地位的办法
与Android和iOS的比拟
在Android中,只管大多数人会应用TextView,然而您能够通过应用StaticLayout,Canvas和Paint类取得低级控件来执行下面列出的所有操作。以下是可用的泛滥选项中的几个:
- Canvas.drawTextOnPath)
- Canvas.drawTextRun)
- Paint.getFontMetrics)
- Paint.measureText)
我在iOS上没有那么低级的文字绘制教训(因为我认为我只会学习在Flutter中做所有事件),然而Core Text具备丰盛的工具集。
Flutter 指南中如此说:
以多个平台为指标的SDK是很常见的……提供可在所有指标平台上运行的API。可怜的是,这通常意味着一个平台或另一个平台独有的性能不可用。对于Flutter,咱们心愿通过明确地成为每个平台的最佳开发方式来防止这种状况。咱们在跨平台上应用的能力仅次于咱们在每个平台上应用的能力。 (增加了重点)
以后,对于须要在应用程序中进行低级文本渲染的咱们当中,Flutter并不是最好的开发平台。
用例
您可能会说Flutter曾经提供了Text和RichText小部件。是的,他们十分好。他们将满足99.9%的开发人员的需要。然而,存在应用较低级别的文本出现工具的用例。
蒙文
我的用例是布局并渲染传统的蒙古文字,该文字垂直书写,并从左到右换行。英语是侧身书写,但CJK和表情符号字符应放弃其失常方向。
有一些应用小部件组合的“解决方案”,然而当您增加文本款式的须要时(例如通过在文本的右侧绘制一条垂直线来“下划线”),一种更牢靠的解决方案是解决所有文本手工测量,安排和绘画。我曾经开始在这里工作了。
中文,日文和韩文
中文,日文和韩文也能够按各种垂直方向进行布局。像蒙古语一样,有一种解决办法,能够解决一次性状况,但对于罕用用法,渲染包会更有帮忙。浏览此内容以更具体地形容需要。
Flutter仅反对反对从右到左和从左到右的布局。不反对(也不反对????)垂直布局。我不会对此示意狐疑。有很多工作。然而我心愿他们会给咱们更多工具来本人做。
艺术文字
进行文字绘画的应用程序也将从对文字绘画工具的低级别拜访中受害。
用文本填充非矩形形态
为了使文本适宜非矩形的内容,您必须进行大量测量。换行在哪里是另一个难题。
#### 文字围绕排除门路流动
这在iOS中可用,但在Flutter中不可用。而且没有简略的办法能够本人实现。
论断
我并不是想压服任何人不要应用Flutter。我还是很喜爱我再也不想回到为不同平台构建同一应用程序的屡次了。
在撰写本文时,我心愿有人会说:“不,你错了。如果您这样做,那么您将能够应用低级文本出现工具。”不过,我对此并没有寄托太大心愿,因为Flutter的次要开发人员之一对此示意:
如果您想要“实在的”垂直文本,并带有强调标记,ruby和内联程度的bidi文本以及所有内容,那么我能提供的最好的方法是,您能够尝试应用咱们提供的较差的原语编写一个程序包来反对此操作,然而可能不会是令人满意的体验。
我真正心愿的是Flutter小组将为咱们提供与UI布局级别一样的文本自在。增加一个dart:ui类以裸露更多LibTxt库并不是特地艰难。确实,保护起来会更多,开发人员可能偶然会用它来编写效率低下的代码,但我认为自在值得付出代价。使Flutter成为应用任何语言开发任何平台的最佳形式。
2020年2月更新
当我最后公布这篇文章时,Flutter团队迅速做出了回应(请参阅上面的评论)。许多工作正在实现(如GitHub问题所记录,谢谢Gary Qian),并且心愿可能会有一些重大的改良。然而,只管受到了强烈反对,但该GitHub问题最终因其工作量过多而被敞开。
我最近得悉,正在实现用Skia SkParagraph模块替换LibTxt的工作。这听起来很令人兴奋,然而我还不晓得细节。您能够在此处跟踪进度。因为这是一项重大更改,因而当初是让Flutter团队理解您的需要与自定义文本出现相干的好时机。请参阅以下局部。
你能够做什么
即便以下问题以后已敞开(只管尚未解决),如果您还须要执行自定义文本出现,请持续对其进行投票并在其上留下评论。
地址:https://github.com/flutter/flutter/issues/35994
为了将问题合成为更小的局部,我增加了以下特定性能要求。如果您还须要它们,请投票和/或评论。
- Need a line/word breaker for custom text rendering #50171
- Need to find how much of a long word could fit in one line before an unnatural line break #51258
我尚未提交任何具体的错误报告,但与许多小型Paragraph对象的测量和绘画效率无关。起因是我本人没有发现任何性能问题。如果您遇到过此类问题,请创立一个具体的GitHub问题,并@suragch me。我会在这里链接到它。
交换
老孟Flutter博客地址(330个控件用法):http://laomengit.com
欢送退出Flutter交换群(微信:laomengit)、关注公众号【老孟Flutter】: