材质文本字段文本向后显示,但CupertinoTextfield文本正确显示Flutter

时间:2020-06-07 10:32:40

标签: flutter textfield

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

这是小部件:

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);
                                    },
                                  ),
                      ),

这是文本检查方法:

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;
    }
  }

3 个答案:

答案 0 :(得分:0)

将近一个月后,由于jwehrle在这里how to set cursor position at the end of the value in flutter in textfield?回答,我找到了解决问题的方法。实际上,我向Flutter团队提出了一个问题,因为在为Material Textfield分配受操纵的文本时CupertinoTextfieldTextEditingController的行为不同,而且似乎与平台有关,我只在Web和iPad。 我认为此解决方案更多是一种变通方法,因为在iOS的CupertinoTextfield中不需要,所以这不是必需的。

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

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

使用中:

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

更新2020年8月8日:

当我升级到Catalina,Android Studio 4.0时,iOS也需要解决方法。不确定是否是由于iOS 13.5或Flutter ..的更改所致。但是在网络上,它现在成对出现乱码。 看起来像固定的东西而破碎的东西。

卡特琳娜(Catalina)上的振奋医生
[✓] Flutter (Channel master, 1.21.0-8.0.pre.98, on Mac OS X 10.15.4 19E287, locale it-IT)
    • Flutter version 1.21.0-8.0.pre.98 at /Users/vinnytwice/Developer/flutter
    • Framework revision 77b4505c80 (31 hours ago), 2020-08-06 18:51:02 -0700
    • Engine revision cd3ea1e839
    • Dart version 2.10.0 (build 2.10.0-3.0.dev fcafd43f2c)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /Users/vinnytwice/Library/Android/sdk
    • Platform android-29, build-tools 30.0.1
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
    • Xcode at /Volumes/ProjectsSSD/Xcode.app/Contents/Developer
    • Xcode 11.5, Build version 11E608c
    • CocoaPods version 1.9.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] Connected device (3 available)
    • iPad Pro (12.9-inch) (4th generation) (mobile) • 08E2351F-A170-4C2E-A8DE-8FED3B5E3124 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-13-5 (simulator)
    • Web Server (web)                               • web-server                           • web-javascript • Flutter
      Tools
    • Chrome (web)                                   • chrome                               • web-javascript • Google
      Chrome 84.0.4147.105

• No issues found!

答案 1 :(得分:0)

class FixedOffsetTextEditingController extends TextEditingController {
  @override
  set text(String newText) {
    value = value.copyWith(
      text: newText,
      selection: TextSelection.collapsed(offset: newText.length),
      composing: TextRange.empty,
    );
  }
}

截至 2021 年 4 月 2 日,这对我有用:)

答案 2 :(得分:0)

我来这里是为了寻找类似的东西,但我很确定它不是 Material TextField 的直接错误,因为如果我在 Android 模拟器上编译并运行它就可以了。然而,在为桌面编译相同的代码时却是错误的。

您是否报告了错误?

对我来说仍然很糟糕@

Flutter 2.0.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision adc687823a (2 weeks ago) • 2021-04-16 09:40:20 -0700
Engine • revision b09f014e96
Tools • Dart 2.12.3

啊哈:这是 gtk+ 版本问题,请参阅:https://github.com/flutter/flutter/issues/47745 - 您至少需要 3.24.27(我有 3.24.26 ... 典型)