我對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】:

相關文章
相關標籤/搜索