【问题标题】:Flutter dateformatter not working correctly颤振日期格式化程序无法正常工作
【发布时间】:2018-05-12 14:54:09
【问题描述】:

*****编辑***** 所以现在我按照我的预期进行了格式化,任何人都知道为什么一旦它在文本字段中,如果他们输入了额外的字符或犯了错误,为什么他们不能退格和删除?这是格式化的工作代码。

    class _DateFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue,
      TextEditingValue newValue
      ) {
    final int newTextLength = newValue.text.length;
    int selectionIndex = newValue.selection.end;
    int usedSubstringIndex = 0;
    final StringBuffer newText = new StringBuffer();
    /*if (newTextLength >= 1) {
      newText.write('');
      if (newValue.selection.end >= 1)
        selectionIndex++;
    }*/
    if (newTextLength >= 2) {
      newText.write(newValue.text.substring(0, usedSubstringIndex = 2) + '/');
      if (newValue.selection.end >= 3)
        selectionIndex += 2;
    }
    if (newTextLength >= 5) {
      newText.write(newValue.text.substring(2, usedSubstringIndex = 4) + '/');
      if (newValue.selection.end >= 5)
        selectionIndex +=2;
    }
    if (newTextLength == 10) {
      newText.write(newValue.text.substring(4, usedSubstringIndex = 8) + '');
      if (newValue.selection.end >= 9)
        selectionIndex +=4;
    }
    // Dump the rest.
    if (newTextLength >= usedSubstringIndex)
      newText.write(newValue.text.substring(usedSubstringIndex));
    return new TextEditingValue(
      text: newText.toString(),
      selection: new TextSelection.collapsed(offset: selectionIndex),
    );
  }
}

感谢任何帮助。还有谁能想到它在 Android 中的工作方式与在 iOS 中不同的原因?

【问题讨论】:

  • 我只是好奇你为什么不直接使用 DatePicker,它对用户更友好?
  • 我的客户希望只输入 10 位数字,他们觉得选择器对于那里的用户来说太麻烦了。
  • 与其复杂化,也许您可​​以在一行中创建 3 个文本字段,分别获取 MM DD YY 的值,并在获得结果时添加“/”。我认为这是一种更简单的方法,可能是可以接受的解决方案,并且不会让用户感到困惑。
  • 是否有一种简单的方法可以自动将焦点移至每个框?
  • 请检查我添加的答案,它可能会有用。

标签: dart flutter


【解决方案1】:

您可以将三个TextFields 中的Row 分别用于(DD/MM/YY)。

使用TextEditingController,您可以根据自己的喜好对输入的文本进行一些限制(例如:日/月 2 个键盘输入,一年 4 个键盘输入)。此外,当达到当前的限制时,您可以转移TextField 的焦点:

  • 使用_dayFocus.unfocus();,从键盘上取消订阅TextField
  • 使用FocusScope.of(context).requestFocus(_monthFocus);,将焦点转移到月份TextField,依此类推。

示例:

代码:

import "package:flutter/material.dart";
import 'package:flutter/src/services/text_editing.dart';

class DateFormat extends StatefulWidget {
  @override
  _DateFormatState createState() => new _DateFormatState();
}

class _DateFormatState extends State<DateFormat> {

  TextEditingController _dayController = new TextEditingController();
  String day = "";
  FocusNode _dayFocus = new FocusNode();
  bool _dayFocused = true;

  TextEditingController _monthController = new TextEditingController();
  String month = "";
  FocusNode _monthFocus = new FocusNode();

  //bool _monthFocused=false;

  TextEditingController _yearController = new TextEditingController();
  String year = "";
  FocusNode _yearFocus = new FocusNode();

  //bool _yearFocused;


  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _scaffoldKey,
      appBar: new AppBar(title: new Text("Date Format"),),
      body: new Row(
        children: <Widget>[ new Flexible (
          child: new TextField(
            keyboardType: TextInputType.datetime,
            autofocus: _dayFocused,
            focusNode: _dayFocus,
            controller: _dayController,
            onChanged: (value) {
              if (value.length <= 2) {
                //save
                day = value;
              }
              else {
                _dayFocus.unfocus();
                FocusScope.of(context).requestFocus(_monthFocus);
                // _monthFocused =true;
                _dayController.value = new TextEditingValue(
                    text: day,
                    composing: new TextRange(
                      start: 0,
                      end: 2,
                    )
                );
              }
            },
          ),),
        new Text("/"),
        new Flexible (
          child: new TextField(
            keyboardType: TextInputType.datetime,
            focusNode: _monthFocus,
            controller: _monthController,
            onChanged: (value) {
              if (value.length <= 2) {
                //save
                month = value;
              }
              else {
                _monthFocus.unfocus();
                FocusScope.of(context).requestFocus(_yearFocus);
                _monthController.value = new TextEditingValue(
                    text: month,
                    composing: new TextRange(
                      start: 0,
                      end: 2,
                    )
                );
              }
            },
          ),),
        new Text("/"),
        new Flexible (
          child: new TextField(
            keyboardType: TextInputType.datetime,
            focusNode: _yearFocus,
            controller: _yearController,
            onChanged: (value) {
              if (value.length <= 4) {
                //save
                year = value;
              }
              else {
                _yearFocus.unfocus();
                _yearController.value = new TextEditingValue(
                    text: year,
                    composing: new TextRange(
                      start: 0,
                      end: 4,
                    )
                );
              }
            },
            onSubmitted: (value) =>
                _scaffoldKey.currentState.showSnackBar(new SnackBar(
                    content: new Text("Your date is $day/$month/$value"))),),),

        ],),);
  }
}

更新

要忽略斜线事件,我们需要用第三个输入更新下一个TextEditingController,使其继续如下:

import "package:flutter/material.dart";
import 'package:flutter/src/services/text_editing.dart';

class DateFormat extends StatefulWidget {
  @override
  _DateFormatState createState() => new _DateFormatState();
}

class _DateFormatState extends State<DateFormat> {

  TextEditingController _dayController = new TextEditingController();
  String day = "";
  FocusNode _dayFocus = new FocusNode();
  bool _dayFocused = true;

  TextEditingController _monthController = new TextEditingController();
  String month = "";
  FocusNode _monthFocus = new FocusNode();

  //bool _monthFocused=false;

  TextEditingController _yearController = new TextEditingController();
  String year = "";
  FocusNode _yearFocus = new FocusNode();

  //bool _yearFocused;


  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _scaffoldKey,
      appBar: new AppBar(title: new Text("Date Format"),),
      body: new Row(
        children: <Widget>[ new Flexible (
          child: new TextField(
            keyboardType: TextInputType.datetime,
            autofocus: _dayFocused,
            focusNode: _dayFocus,
            controller: _dayController,
            onChanged: (value) {
              if (value.length <= 2) {
                //save
                day = value;
              }
              else {
                _dayFocus.unfocus();
                _monthController.text = value[2];
                _monthController.selection=new TextSelection.collapsed(offset: 1);
                FocusScope.of(context).requestFocus(_monthFocus);
                // _monthFocused =true;
                _dayController.value = new TextEditingValue(
                    text: day,
                    composing: new TextRange(
                      start: 0,
                      end: 2,
                    )
                );
              }
            },
          ),),
        new Text("/"),
        new Flexible (
          child: new TextField(
            keyboardType: TextInputType.datetime,
            focusNode: _monthFocus,
            controller: _monthController,
            onChanged: (value) {
              if (value.length <= 2) {
                //save
                //_monthController.text = value;
                month = value;

              }
              else {
                _yearController.text = value[2];
                _yearController.selection=new TextSelection.collapsed(offset: 1);
                _monthFocus.unfocus();
                FocusScope.of(context).requestFocus(_yearFocus);
                _monthController.value = new TextEditingValue(
                    text: month,
                   // selection: new TextSelection(baseOffset: 1, extentOffset: 1),
                    composing: new TextRange(
                      start: 0,
                      end: 2,
                    )
                );
              }
            },
          ),),
        new Text("/"),
        new Flexible (
          child: new TextField(
            keyboardType: TextInputType.datetime,
            focusNode: _yearFocus,
            controller: _yearController,
            onChanged: (value) {
              if (value.length <= 4) {
                //save
                year = value;
              }
              else {
                _yearFocus.unfocus();
                _yearController.value = new TextEditingValue(
                    text: year,
                    composing: new TextRange(
                      start: 0,
                      end: 4,
                    )
                );
              }
            },
            onSubmitted: (value) =>
                _scaffoldKey.currentState.showSnackBar(new SnackBar(
                    content: new Text("Your date is $day/$month/$value"))),),),

        ],),);
  }
}

【讨论】:

  • 感谢您的示例,但它并不能避免用户必须交互移动选择,我想尝试将其保持为 10 个输入,我知道这听起来很极端,但客户想要他们想要的,我认为将我在 JS 中所做的事情并使其工作很容易,但事实并非如此,也许有人会看到如何使格式化程序正常工作。感谢您的帮助。
  • 我的意思是 8 个输入。
  • 是的,我以为您的意思是 8 个输入,请检查答案中的更新部分。
  • 这很好用!我只有一个问题,有什么方法可以检测退格并返回到最后一个文本字段。谢谢
猜你喜欢
  • 2019-08-29
  • 1970-01-01
  • 1970-01-01
  • 2014-10-07
  • 2019-04-10
  • 2021-11-07
  • 2021-08-07
  • 2020-05-20
  • 1970-01-01
相关资源
最近更新 更多