Robert
Robert

Reputation: 5865

Flutter dateformatter not working correctly

*****EDIT******* So now I have it formatting as I expect, anyone have an idea why once it is in the textfield, if they type an extra character or make a mistake why they would not be able to backspace and delete? Here is the working code for formatting.

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

Any help is appreciated. Also can anyone think of a reason it does not work the same in Android as in iOS?

Upvotes: 0

Views: 2135

Answers (1)

Shady Aziza
Shady Aziza

Reputation: 53327

You can use a Row of three TextFields for (DD/MM/YY) respectively.

Using TextEditingController you can put some limits on your text being typed however you like (e.g: 2 keyboard inputs for day/month, 4 for a year). Moreover, you can shift the focus of the TextField when the limits of the current one has been reached:

  • Using _dayFocus.unfocus(); , unsubscribes the day TextField from the keyboard.
  • Using FocusScope.of(context).requestFocus(_monthFocus); , shifts the focus to the month TextField, and so on.

Example:

enter image description here

Code:

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"))),),),

        ],),);
  }
}

UPDATE

To ignore the slash event, we need to update the next TextEditingController with the third input so it carries on like this:

enter image description here

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"))),),),

        ],),);
  }
}

Upvotes: 1

Related Questions