我对Flutter的第一次失望

老孟导读:此文翻译自:https://medium.com/@suragch/my-first-disappointment-with-flutter-5f6967ba78bfhtml

我喜欢Flutter。我喜欢开发一次并让代码在Android和iOS上运行。我喜欢节省多少时间。我喜欢如今成为一名Web开发人员,而无需作任何额外的工做。我喜欢hot reload。我喜欢经过将小部件组合到布局中来快速构建UI。我喜欢制做ListView简单得多。我喜欢状态管理。 (好吧,只是在开玩笑。可是我能够应付。)我喜欢Dart。我喜欢Future和async / await比Android AsyncTasks甚至iOS Dispatch Queue容易得多。java

可是,在花了最后两周的时间研究Flutter如何呈现文本后,我对使用的工具感到失望。android

咱们被告知:ios

Flutter的分层体系结构使您能够控制屏幕上的每一个像素。git

这显然不适用于用于绘制文本的像素。github

Flutter中的低级文字功能

Flutter使用名为LibTxt的库结合使用Skia,Hafbuzz,Minikin和ICU来呈现文本。开发人员在使用Text小部件或TextSpan甚至是TextPainter时间接使用它。在最低级别上,咱们可使用dart:iu,它是使用ParagraphBuilder构建的Paragraph类。这些类基本上只是底层LibTxt引擎的包装器。几乎全部工做都由此引擎完成,而在dart:ui中几乎没有暴露。ruby

Paragraph类为咱们提供了如下控制:微信

  • Size:我能够获取整个渲染段落的宽度和高度,它能够是单行或多行。
  • 距基线的距离(仅对于第一行)
  • 文本是否溢出了maxLines变量。
  • 文本框的大小和相对位置。这是一个例子:

  • 最接近某个像素位置的文本字符索引。在上面的示例中,像素(一、1)对应于字符串中的索引0,即“My text line.”的字母“ M”。
  • 字符串中某些字符偏移的单词边界。

随后的更新也为咱们提供了LineMetrics,它为每行提供了许多详细信息:app

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;
}

可是,咱们没有获得:async

  • 一种在文本框中获取实际文本的方法。
  • 一种控制文本布局方式的方法。
  • 一种在路径上绘制文本的方法。
  • 一种无需绘制整个段落便可测量和绘制短文本的方法。
  • 一种从文本字符串获取换行位置的方法

与Android和iOS的比较

在Android中,尽管大多数人会使用TextView,可是您能够经过使用StaticLayout,Canvas和Paint类得到低级控件来执行上面列出的全部操做。如下是可用的众多选项中的几个:

我在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

为了将问题分解为更小的部分,我添加了如下特定功能要求。若是您还须要它们,请投票和/或评论。

我还没有提交任何具体的错误报告,但与许多小型Paragraph对象的测量和绘画效率有关。缘由是我本身没有发现任何性能问题。若是您遇到过此类问题,请建立一个详细的GitHub问题,并@suragch me。我会在这里连接到它。

交流

老孟Flutter博客地址(330个控件用法):http://laomengit.com

欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】: