在Flutter中输入框是重度交互运用场景,但其中许多坑爹体会问题一直官方都没给出好的解决计划,本文将介绍一些Flutter输入框的坑爹问题;
1. Android未输入字符韶光标高度小于输入字符时高度
详细表现行为如下:
此小细节问题在稀土/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为输入字符和输入字符高度改变如下:
因而光标区域高度
未输入字符时:cursorHeight = 21.0 – 0.0 = 21.0 ;
输入字符时:cursorHeight = 20.0 – (-1.0) = 21.0 ;
高度未发生改变,能够发现其实iOS也存在一个像素偏差,只是肉眼不易发现而言;
Android渠道
在Android渠道下测验未输入字符高度和输入字符高度改变如下:
未输入字符时: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的最小高度设置
此问题怎么说呢,是个问题也不算什么大问题,首要场景在类似微信输入框自成长高度时分场景会呈现
在实践这个微信键盘输入成长事例时分会发现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体会小细节还需要继续打磨打磨,其他它逐步完善吧~