Material Textfield 文本向后显示,但 CupertinoTextfield 文本正确显示 Flutter

Vin*_*nzo 4 textfield flutter

我有一个与其连接的文本字段TextEditingController()。在onChanged:回调中,我执行文本检查以仅允许时间输入。当在 iOS 上运行CupertinoTextfield并且其行为符合预期时,每次输入光标都会移动,因此下一个数字位于正确的位置,因此输入 1000 将得到 10:00。当在网络或 Android 上运行Material Textfield时,问题是当光标停留在第一个位置时文本向后显示,因此输入 1000 将导致 00:01 ..我尝试启用autofocus: true,但没有帮助。我尝试过textDirection: TextDirection.ltr,但也没有修复。我还尝试了另一篇文章中的解决方案,抓取控制器选择并将其重新应用到选中的文本上,但它也没有帮助。我缺少为 Material Textfield 设置什么?一如既往,非常感谢您的时间和帮助。

这是小部件:

Expanded(
                        flex: 2,
                        child: kIsWeb
                            ? TextField(
                                keyboardType: TextInputType.numberWithOptions(),
                                textDirection: TextDirection.ltr,
                                autofocus: true,
                                controller: monMorOp,
                                onChanged: (value) {
                                  TextSelection previousSelection =
                                      monMorOp.selection;
                                  monMorOp.text = validateTimeFormat(value);
                                  monMorOp.selection = previousSelection;
                                },
                              )
                            : Platform.isIOS
                                ? CupertinoTextField(
                                    keyboardType:
                                        TextInputType.numberWithOptions(),
                                    controller: monMorOp,
                                    onChanged: (value) {
                                      monMorOp.text = validateTimeFormat(value);
                                    },
                                  )
                                : TextField(
                                    keyboardType:
                                        TextInputType.numberWithOptions(),
                                    controller: monMorOp,
                                    onChanged: (value) {
                                      monMorOp.text = validateTimeFormat(value);
                                    },
                                  ),
                      ),
Run Code Online (Sandbox Code Playgroud)

这是文本检查方法:

String validateTimeFormat(String value) {
    print('call back method called');
//    String numb = event.text;
    print('input text is $value');
    String cleanNumb = value.replaceAll(RegExp(':'), '').substring(0);
    print('cleaned input text is $cleanNumb');
    RegExp isDigit = RegExp(r'^[\d]{1,4}$'); // is digit 1 to 4 characters
//    RegExp isDigit = RegExp(r'^[\d]$'); // is digit
    RegExp input;
    String text;
    int lenght;
    String replaced;

    if (isDigit.hasMatch(cleanNumb)) {
      print('text is 1-4 digits');
      text = cleanNumb;
      lenght = text.length;
//      print('lenght is $lenght');

      if (lenght == 1) {
        // first digit
        //allow 0-2
        input = RegExp(r'^[0-2]$');
        input.hasMatch(text[0])
            ? print('text is : $text')
            : print('text is: not valid');
        return input.hasMatch(text[lenght - 1]) ? text : '';
      } else if (lenght == 2) {
        // second digit
        int first = int.parse(text[0]);
        print('firstDigit is $first');
        if (first == 008 || first == 1) {
          // allow 0-9
          input = RegExp(r'^[0-9]$');
          input.hasMatch(text[lenght - 1])
              ? print('text is : $text')
              : print('text is : ${text.substring(0, lenght - 1)}');
          return input.hasMatch(text[lenght - 1])
              ? text
              : text.substring(0, lenght - 1);
        } else {
          // allow 0-3
          input = RegExp(r'^[0-3]$');
          input.hasMatch(text[lenght - 1])
              ? print('text is : $text')
              : print('text is : ${text.substring(0, lenght - 1)}');
          return input.hasMatch(text[lenght - 1])
              ? text
              : text.substring(0, lenght - 1);
        }
      }
      if (lenght == 3) {
        //third digit
        // add : at lenght-1
        // allow 0-5
        input = RegExp(r'^[0-5]$');
        input.hasMatch(text[lenght - 1])
            ? replaced = text.replaceRange(2, lenght, ':${text.substring(2)}')
            : replaced = text.substring(0, lenght - 1);
        print('text is : $replaced');
        return replaced;
      }
      if (lenght == 4) {
        // fourth digit
        // allow 0-9
        input = RegExp(r'^[0-9]$');
        input.hasMatch(text[lenght - 1])
            ? replaced = text.replaceRange(2, lenght, ':${text.substring(2)}')
            : replaced = text.substring(0, lenght - 1);
        print('text is : $replaced');
        return replaced;
      }
    } else {
      // discard extra digit
      print('more than 4 digits');
      lenght = cleanNumb.length;
      replaced =
          cleanNumb.replaceRange(2, lenght, ':${cleanNumb.substring(2, 4)}');
      print('text is : $replaced');
      return replaced;
    }
  }
Run Code Online (Sandbox Code Playgroud)

Vin*_*nzo 6

差不多一个月后,我找到了问题的解决方案,感谢 jwehrle 的回答,如何在文本字段中的颤动中将光标位置设置在值的末尾?。实际上,我向 Flutter 团队提交了一个问题,因为它的行为与向其分配操纵文本时Material Textfield不同,而且它似乎与平台相关,我只在 Web 和 iPad 上测试了它。\n我认为这个解决方案更多的是一种解决方法,因为这应该不是必需的,因为iOS 上不需要。CupertinoTextfieldTextEditingControllerCupertinoTextfield

\n

onChanged:回调中将操作的输入文本分配给控制器后添加以下内容:

\n

textfieldController.selection = TextSelection.fromPosition(TextPosition(offset: textfieldController.text.length));

\n

正在使用:

\n
Expanded(\n                        flex: 2,\n                        child: UniversalPlatform.isWeb\n                            ? TextField(\n                                keyboardType: TextInputType.numberWithOptions(),\n                                textDirection: TextDirection.ltr,\n                                autofocus: true,\n                                controller: monMorOp,\n                                style: TextStyle(\n                                    color: Colors.white,\n                                    fontSize: 15,\n                                    fontWeight: FontWeight.w500),\n                                onChanged: (value) {\n                                  monMorOp.text = validateTimeFormat(value);\n                                  monMorOp.selection =\n                                      TextSelection.fromPosition(TextPosition(\n                                          offset: monMorOp.text.length));\n                                },\n                              )\n                            : UniversalPlatform.isIOS\n                                ? CupertinoTextField(\n                                    keyboardType:\n                                        TextInputType.numberWithOptions(),\n                                    controller: monMorOp,\n                                    style: TextStyle(\n                                        color: Colors.white,\n                                        fontSize: 15,\n                                        fontWeight: FontWeight.w500),\n                                    onChanged: (value) {\n                                      monMorOp.text = validateTimeFormat(value);\n                                    },\n                                  )\n                                : TextField(\n                                    keyboardType:\n                                        TextInputType.numberWithOptions(),\n                                    controller: monMorOp,\n                                    style: TextStyle(\n                                        color: Colors.white,\n                                        fontSize: 15,\n                                        fontWeight: FontWeight.w500),\n                                    onChanged: (value) {\n                                      monMorOp.text = validateTimeFormat(value);\n                                      monMorOp.selection =\n                                          TextSelection.fromPosition(\n                                              TextPosition(\n                                                  offset:\n                                                      monMorOp.text.length));\n                                    },\n                                  ),\n                      ),\n
Run Code Online (Sandbox Code Playgroud)\n

2020 年 8 月 8 日更新:

\n

当我升级到 Catalina、Android Studio 4.0 时,iOS 现在也需要解决方法。不确定是否是由于 iOS 13.5 或 Flutter 中的更改所致。但在网络上,它现在会成对打乱数字。\n看起来修复了某些内容,但又破坏了其他内容。

\n

Catalina 上的颤振医生:

\n
[\xe2\x9c\x93] Flutter (Channel master, 1.21.0-8.0.pre.98, on Mac OS X 10.15.4 19E287, locale it-IT)\n    \xe2\x80\xa2 Flutter version 1.21.0-8.0.pre.98 at /Users/vinnytwice/Developer/flutter\n    \xe2\x80\xa2 Framework revision 77b4505c80 (31 hours ago), 2020-08-06 18:51:02 -0700\n    \xe2\x80\xa2 Engine revision cd3ea1e839\n    \xe2\x80\xa2 Dart version 2.10.0 (build 2.10.0-3.0.dev fcafd43f2c)\n\n \n[\xe2\x9c\x93] Android toolchain - develop for Android devices (Android SDK version 30.0.1)\n    \xe2\x80\xa2 Android SDK at /Users/vinnytwice/Library/Android/sdk\n    \xe2\x80\xa2 Platform android-29, build-tools 30.0.1\n    \xe2\x80\xa2 Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java\n    \xe2\x80\xa2 Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)\n    \xe2\x80\xa2 All Android licenses accepted.\n\n[\xe2\x9c\x93] Xcode - develop for iOS and macOS (Xcode 11.5)\n    \xe2\x80\xa2 Xcode at /Volumes/ProjectsSSD/Xcode.app/Contents/Developer\n    \xe2\x80\xa2 Xcode 11.5, Build version 11E608c\n    \xe2\x80\xa2 CocoaPods version 1.9.3\n\n[\xe2\x9c\x93] Chrome - develop for the web\n    \xe2\x80\xa2 Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome\n\n[\xe2\x9c\x93] Android Studio (version 4.0)\n    \xe2\x80\xa2 Android Studio at /Applications/Android Studio.app/Contents\n    \xe2\x80\xa2 Flutter plugin version 47.1.2\n    \xe2\x80\xa2 Dart plugin version 193.7361\n    \xe2\x80\xa2 Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)\n\n[\xe2\x9c\x93] Connected device (3 available)\n    \xe2\x80\xa2 iPad Pro (12.9-inch) (4th generation) (mobile) \xe2\x80\xa2 08E2351F-A170-4C2E-A8DE-8FED3B5E3124 \xe2\x80\xa2 ios            \xe2\x80\xa2\n      com.apple.CoreSimulator.SimRuntime.iOS-13-5 (simulator)\n    \xe2\x80\xa2 Web Server (web)                               \xe2\x80\xa2 web-server                           \xe2\x80\xa2 web-javascript \xe2\x80\xa2 Flutter\n      Tools\n    \xe2\x80\xa2 Chrome (web)                                   \xe2\x80\xa2 chrome                               \xe2\x80\xa2 web-javascript \xe2\x80\xa2 Google\n      Chrome 84.0.4147.105\n\n\xe2\x80\xa2 No issues found!\n
Run Code Online (Sandbox Code Playgroud)\n

2021 年 2 月 4 日更新

\n

而不是在文本格式化后将新文本字段的值从onChanged回调分配给它的控制器参数.text

\n
monMorOp.text = validateTimeFormat(value);\n
Run Code Online (Sandbox Code Playgroud)\n

然后通过偏移控制器的.text.length数量来替换控制器选择:

\n
monMorOp.selection = TextSelection.fromPosition(TextPosition(offset: monMorOp.text.length));\n
Run Code Online (Sandbox Code Playgroud)\n

现在,我将新的格式化文本字段文本分配给控制器.value,并按文本字段的格式化值偏移其选择位置,如下所示

\n
 onChanged: (value) {\n     value = validateTimeFormat(value);\n     monMorCl.value = TextEditingValue(\n           text: value,\n           selection: TextSelection.collapsed(offset: value.length));\n },\n
Run Code Online (Sandbox Code Playgroud)\n

希望它能帮助其他人,因为我发现最近随着 Flutter/Dart 的更新,情况发生了很大的变化。\n干杯

\n