Flutter 自定義輸入框Selection選單和選擇器

法的空間發表於2019-08-05

extended_text_field 相關文章

Flutter 1.7.8穩定版本(Flutter Releases可以通過該地址,查詢各個branch的當前版本)已經發布了一段時間了,Flutter Candies全家桶也在第一時間進行了升級支援。

文字選擇控制器

看過我文章的人應該知道,我在ExtendedText上面實現了文字選擇,可以通過設定TextSelectionControls來自定義Selection選單和選擇器。

不是很明白為啥官方的輸入框不將這個屬性暴露出來,歪果仁能忍受這種溢位嗎?中文比較短應該不會溢位,但是英文會溢位,沒有人提出來過嗎?

Flutter 自定義輸入框Selection選單和選擇器

定義控制器

於是我提供了預設的控制器MaterialExtendedTextSelectionControls/CupertinoExtendedTextSelectionControls

你可以通過繼承他們,實現buildToolbar方法和buildHandle方法來自定義選單和選擇器。 當然你也可以直接繼承TextSelectionControls寫完整的一套,下面是我demo裡面的效果。

Flutter 自定義輸入框Selection選單和選擇器

abstract class TextSelectionControls {
  /// Builds a selection handle of the given type.
  ///
  /// The top left corner of this widget is positioned at the bottom of the
  /// selection position.
  Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight);

  /// Builds a toolbar near a text selection.
  ///
  /// Typically displays buttons for copying and pasting text.
  ///
  /// [globalEditableRegion] is the TextField size of the global coordinate system
  /// in logical pixels.
  ///
  /// [textLineHeight] is the `preferredLineHeight` of the [RenderEditable] we
  /// are building a toolbar for.
  ///
  /// The [position] is a general calculation midpoint parameter of the toolbar.
  /// If you want more detailed position information, can use [endpoints]
  /// to calculate it.
  Widget buildToolbar(
    BuildContext context,
    Rect globalEditableRegion,
    double textLineHeight,
    Offset position,
    List<TextSelectionPoint> endpoints,
    TextSelectionDelegate delegate,
  );
}
複製程式碼

使用控制器

  /// An interface for building the selection UI, to be provided by the
  /// implementor of the toolbar widget or handle widget
  final TextSelectionControls textSelectionControls;
  
    ExtendedTextField(
            textSelectionControls: _myExtendedMaterialTextSelectionControls,
            specialTextSpanBuilder: _mySpecialTextSpanBuilder,
            controller: controller,
            maxLines: null,
          ),
複製程式碼

WidgetSpan

1.7.8 中一個主要對全家桶的影響是,官方出了一個WidgetSpan,支援在文字中嵌入Widget。看過之前關於文字的小夥伴都知道,之前 Flutter RichText支援圖片顯示和自定義圖片效果,是通過佔位Span,然後在位置上面繪畫出來圖片來實現的。其實官方的思路也是一樣,先通過佔位,然後在對應的位置講widget給繪製出來。

這對我之前的程式碼也很大影響,就是說需要支援WidgetSpan的Selection,在實現過程中也發現一些問題,WidgetSpan 異常和發現TextPainter提供的WidgetSpan位置不正確。最後我通過一些Workaround,暫時解決這些問題,實現extended_Textextended_text_field對WidgetSpan的支援。

下面是使用WidgetSpan 和extended_text_field 做的一個郵箱的demo,因為之前群裡小夥伴有提到這個需求,我當時就考慮使用extended_text_field 是一種簡單的方式

Flutter 自定義輸入框Selection選單和選擇器

更多詳情,請檢視demo

1.7.8更多的問題

後面三個問題,在ExtendedTextExtendedTextField已進行修復,如果你是使用的官方輸入框或者Text,請注意下這些問題。

如何使用舊的三方外掛版本

1.7.8 可以說成為了最不穩定的一個穩定版本,所以很多小夥伴體會到了之後。很快就回退了到1.5.4版本。但是很多三方外掛都已經更新api到1.7.8,因為1.5.4到1.7.8之間有大量api的改動,俗稱breaking change,那麼該怎麼使用之前的舊的版本呢?

ExtendedImage舉個例子,隨便說下,國內的小夥伴直接使用pub國內映象搜尋外掛吧,那個官方的經常打不開

Flutter 自定義輸入框Selection選單和選擇器

可以看到0.5.3 對程式碼基於1.7.8進行了改動,也就是說你回滾到了1.5.4版本,那麼需要引用的是0.5.1版本。

extended_image: ^0.5.1 這樣寫是沒有用的,依然會下載最新的0.5.3,箭頭的是0.5.1以及之上

引用如下圖,記住去掉箭頭,因為extended_image 引用了extended_image_library,所以你也需要引用並且去掉箭頭。

Flutter 自定義輸入框Selection選單和選擇器

你可以先extended_image: 0.5.1 下載到了0.5.1到本地,然後通過開啟.packages檔案找到extended_image的下載位置,

開啟0.5.1版本的extended_image,找出它所引用的其他庫

Flutter 自定義輸入框Selection選單和選擇器

什麼時候選擇更新Flutter版本

對於生產環境的小夥伴,建議不要有了更新就進行更新。你要確保三方庫都已經更新到最新的版本,而且建議緩緩再更新,因為你不知道又新加入了多少bug

Flutter 自定義輸入框Selection選單和選擇器

一般來說我們可以以pub上編譯結果為準,可以看到現在pub是以1.7.8+hotfix.3進行編譯的。畢竟每個外掛的作者,都不希望自己的外掛編譯扣分,哈哈哈

Flutter 自定義輸入框Selection選單和選擇器

對master分支勇士的一些建議

1.5.4到1.7.8的過渡中,一些敢為嚐鮮的小夥伴一直在master分支上面,導致一些三方外掛各種報錯。這裡提一下,從穩定性來說,beta>stable>dev>master,請根據自己的情況來選擇分支。

對於這部分的小夥伴,我只能說可以開一個外掛分支給你,希望你能pr最新branch上來,然後提供給其他同樣需要的小夥伴。

具體引用方式,我們可以採取git的方式來引用,ref為選擇的分支

  extended_image:
    git:
      url: https://github.com/fluttercandies/extended_image.git
      ref: dev
複製程式碼

歡迎大家踴躍PR。

結語

最後放上 extended_text_field,如果你有什麼不明白或者對這個方案有什麼改進的地方,請告訴我,歡迎加入Flutter Candies,一起生產可愛的Flutter 小糖果(QQ群:181398081)

最最後放上Flutter Candies全家桶,真香。

Flutter 自定義輸入框Selection選單和選擇器

相關文章