承接上文:《Flutter 多引擎烘托,在稿定 App 的实践(三):躺坑篇》

先吐槽,这多引擎烘托的坑真的是多,但好在努尽力也都能处理掉 ~

这次对 TextField 单独开一篇说明,也算是把上文未完善的

M. Flutter 开发需求留心的 Root 不是一个MaterialApp 会发生的问题

一次性完善掉了。

起因

笔者在开发一个通用输入框组件,在测试用例中彻底正常,如下图

Flutter 多引擎烘托,TextField 踩坑攻略

但是通过 FlutterEngineGroup 多引擎烘托集成到 Native 项目时,报错如下:

Flutter 多引擎烘托,TextField 踩坑攻略

处理办法

看报错信息得知, TextField 竟然需求一个 Material 父节点 [狗头] …

也去翻一下 TextField 源码,看到如下的注释:

Flutter 多引擎烘托,TextField 踩坑攻略

的确需求用 decoration 来绘制全边框的款式,那就乖乖听话,补上应该就行了吧。

Material(
  child: TextField(...)
)

假如各位同学没看前几篇文章,直接看这篇可能会问为什么不必 MaterialApp or Scaffold。那建议仍是翻一下前几篇文章,还不是一两句能说清的。

但报错就变成:

Flutter 多引擎烘托,TextField 踩坑攻略

WTF,还要 MaterialLocalizations ???

我也是无力吐槽了,网上翻了翻,大部分都是说用 MaterialApp,但是多引擎烘托下又用不了它,真的怪不得用的人那么少。

好在,翻到官方文档(最后的救命稻草)TextField requires a MaterialLocalizations widget

可以看到这是一篇搬迁文档,在 Flutter 1.20 年代,TextField 增加了必要 Material

搬迁文档写的很具体,所以直接可以用它搬迁后的写法,也算是一个全家桶,假如不必 MaterialApp,那应该去运用的父节点同时介绍了出来,有些多,所以就简略封装了下来运用

class MaterialWidget extends StatelessWidget {
  final Widget child;
  const MaterialWidget({Key? key, required this.child}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Localizations(
      locale: const Locale('en', 'US'),
      delegates: const <LocalizationsDelegate<dynamic>>[
        DefaultWidgetsLocalizations.delegate,
        DefaultMaterialLocalizations.delegate,
      ],
      child: MediaQuery(
        data: const MediaQueryData(),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            color: Colors.transparent,
            child: child,
          ),
        ),
      ),
    );
  }
}

然后,把“主动生成”的模版代码中的 Directionality 替换为 MaterialWidget,来防止团队内其他人踩坑。

其他留心事项

TextField 在多引擎烘托下运用还有些其他问题:

不能运用引荐的键盘弹出监听

Flutter 官方引荐运用的

/// 办法1
Scaffold(
  resizeToAvoidBottomInset: true,
  child: ...
)
/// 办法2
Container(
  padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
  child: ...,
);

这两种办法都是不能用的,笔者的处理办法是在 Native 封装监听,由 Native 来操控 View 位置上移。

留心 Material 自带背景色

所以笔者在封装的基类中增加了 color: Colors.transparent

==== 2022.10.19 继续掉坑分割线 ====

留心需求父节点还需求是一个 Overlay

Flutter 多引擎烘托,TextField 踩坑攻略

Debug 下会 assert 到这个位置,页面显现是正常的,但键盘输入成果你收不到 !!!

TextFieldonChange 事件没反应 !!!

直接放改后的代码:

  @override
  Widget build(BuildContext context) {
    return MaterialWidget(
      child: Overlay(
        initialEntries: [
          OverlayEntry(
            builder: (context) {
              return ...
            },
          ),
        ],
      ),
    );
  }