Flutter 自定义输入框Selection菜单和选择器

7,354 阅读5分钟

extended_text_field 相关文章

Flutter 1.7.8稳定版本(Flutter Releases可以通过该地址,查询各个branch的当前版本)已经发布了一段时间了,Flutter Candies全家桶也在第一时间进行了升级支持。

文本选择控制器

看过我文章的人应该知道,我在ExtendedText上面实现了文本选择,可以通过设置TextSelectionControls来自定义Selection菜单和选择器。

不是很明白为啥官方的输入框不将这个属性暴露出来,居然大家能忍受这种溢出吗?中文比较短应该不会溢出,但是英文会溢出,没有人提出来过吗?

定义控制器

于是我提供了默认的控制器MaterialExtendedTextSelectionControls/CupertinoExtendedTextSelectionControls

你可以通过继承他们,实现buildToolbar方法和buildHandle方法来自定义菜单和选择器。 当然你也可以直接继承TextSelectionControls写完整的一套,下面是我demo里面的效果。

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 是一种简单的方式

更多详情,请查看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国内镜像搜索插件吧,那个官方的经常打不开

可以看到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,所以你也需要引用并且去掉箭头。

你可以先extended_image: 0.5.1 下载到了0.5.1到本地,然后通过打开.packages文件找到extended_image的下载位置,

打开0.5.1版本的extended_image,找出它所引用的其他库

什么时候选择更新Flutter版本

对于生产环境的小伙伴,建议不要有了更新就进行更新。你要确保三方库都已经更新到最新的版本,而且建议缓缓再更新,因为你不知道又新加入了多少bug

一般来说我们可以以pub上编译结果为准,可以看到现在pub是以1.7.8+hotfix.3进行编译的。毕竟每个插件的作者,都不希望自己的插件编译扣分,哈哈哈

对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全家桶,真香。