Flutter输入框是重度交互运用场景,但其中许多坑爹体会问题一直官方都没给出好的解决计划,本文将介绍一些Flutter输入框的坑爹问题;

1. Android未输入字符韶光标高度小于输入字符时高度

详细表现行为如下:

Flutter TextFiled的哪些坑

Flutter TextFiled的哪些坑

此小细节问题在稀土/B站漫画/青藤之恋等运用Flutter的APP都存在,首要原因运用官方在运用定义iOS/Android两个渠道的光标有不同完成机制;中心完成类在Editable.dart中

  void _computeCaretPrototype() {
    assert(defaultTargetPlatform != null);
    switch (defaultTargetPlatform) {
      case TargetPlatform.iOS:
      case TargetPlatform.macOS:
        _caretPrototype = Rect.fromLTWH(0.0, 0.0, cursorWidth, cursorHeight + 2);
        break;
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.windows:
        _caretPrototype = Rect.fromLTWH(0.0, _kCaretHeightOffset, cursorWidth, cursorHeight - 2.0 * _kCaretHeightOffset);
        break;
    }
  }

iOS渠道

试验测验iOS为输入字符和输入字符高度改变如下:

Flutter TextFiled的哪些坑

Flutter TextFiled的哪些坑

因而光标区域高度

未输入字符时:cursorHeight = 21.0 – 0.0 = 21.0 ;

输入字符时:cursorHeight = 20.0 – (-1.0) = 21.0 ;

高度未发生改变,能够发现其实iOS也存在一个像素偏差,只是肉眼不易发现而言;

Android渠道

在Android渠道下测验未输入字符高度和输入字符高度改变如下:

Flutter TextFiled的哪些坑

Flutter TextFiled的哪些坑

未输入字符时:cursorHeight = 17.0 – 2.0 = 15.0 ;

输入字符时: cursorHeight = 19.0 – 0.3 = 18.7 ;

因而能够显着看出Android渠道下输入字符后光标突然变大了一些;

修正计划

能够参阅之前提过的PR:github.com/flutter/flu…

中心修正就是将Android渠道核算光标高度和iOS保持一致,FIX-ADD 代码如下:


  void paintRegularCursor(Canvas canvas, RenderEditable renderEditable, Color caretColor, TextPosition textPosition) {
    ...
    caretRect = caretRect.shift(renderEditable._paintOffset);
    ///FIX-ADD
    caretRect = Rect.fromLTRB(caretRect.left, 0.0, caretRect.right, renderEditable.cursorHeight + 2.0);
    final Rect integralRect = caretRect.shift(renderEditable._snapToPhysicalPixel(caretRect.topLeft));
    ...
  }

2. 输入框自动读取粘贴板

这个问题在一些Flutter2.x版别存在(在高版别3.0后应该已经修正),特别是在小米手机上因为照明弹很简单引起监管问题突出,中心也是这个TextFiled的基类text_selection.dart中:

github.com/flutter/flu…

github.com/flutter/flu…

  /// Check the [Clipboard] and update [value] if needed.
  Future<void> update() async {
    switch (defaultTargetPlatform) {
      // Android 12 introduces a toast message that appears when an app reads
      // the content on the clipboard. To avoid unintended access, both the
      // Flutter engine and the Flutter framework need to be updated to use the
      // appropriate API to check whether the clipboard is empty.
      // As a short-term workaround, always show the paste button.
      // TODO(justinmc): Expose `hasStrings` in `Clipboard` and use that instead
      // https://github.com/flutter/flutter/issues/74139
      case TargetPlatform.android:
      // Intentionally fall through.
      // iOS 14 added a notification that appears when an app accesses the
      // clipboard. To avoid the notification, don't access the clipboard on iOS,
      // and instead always show the paste button, even when the clipboard is
      // empty.
      // TODO(justinmc): Use the new iOS 14 clipboard API method hasStrings that
      // won't trigger the notification.
      // https://github.com/flutter/flutter/issues/60145
      case TargetPlatform.iOS:
        value = ClipboardStatus.pasteable;
        return;
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.macOS:
      case TargetPlatform.windows:
        break;
    }
    ClipboardData? data;
    try {
      data = await Clipboard.getData(Clipboard.kTextPlain);
    } catch (stacktrace) {
      // In the case of an error from the Clipboard API, set the value to
      // unknown so that it will try to update again later.
      if (_disposed || value == ClipboardStatus.unknown) {
        return;
      }
      value = ClipboardStatus.unknown;
      return;
    }
    ...
  }

这里的在Android/iOS渠道下提前return不走下面读取体系粘贴板方法了;

3. TextFiled的最小高度设置

此问题怎么说呢,是个问题也不算什么大问题,首要场景在类似微信输入框自成长高度时分场景会呈现

Flutter TextFiled的哪些坑

Flutter TextFiled的哪些坑

在实践这个微信键盘输入成长事例时分会发现TextFiled无法设置最小高度,这个首要因为TextFiled内部核算最小高度大概是48,因而当输入一行的最小高度<48时分,TextFiled是无法满足需求的,此时你能够换CupertinoTextField完成类似作用,不独自展诉此问题~

4. 监听体系键盘弹出收缩状态

现在Flutter在这个API没有供给,一些第三方插件完成思路大多数监听viewInsets.bottom,

详细中心代码如下所示:

MediaQuery.of(context).viewInsets.bottom > 0 ? '键盘弹出''键盘收起'

正常场景下此方法没有任何问题,可是就怕骚操作场景会呈现一些异常现象,如果各位有更好的方法费事奉告下我,谢谢~

5. 焦点控制和输入框顶起

焦点控制类是FocusNode运用,中心代码如下:

      ///获取焦点      
      FocusScope.of(context).requestFocus(focusNode);
      ///释放焦点
      focusNode?.unfocus();

输入框因键盘顶起中心设置 resizeToAvoidBottomPadding

总括

从运用来看,的确坑有点多,现在来看Flutter体会小细节还需要继续打磨打磨,其他它逐步完善吧~