Date and Time pickers in Flutter. Let’s explore!

As Flutter is growing toward its utmost potential, the count of its developers is increasing rapidly. No one can doubt the user experience they receive during their development with this framework. With that being said, let’s shed some light on Date and Time pickers in Flutter.


Table of Contents

Project Structure

Consider a project having two:

  • Customized TextFormFields, for date and time respectively vis-à-vis, using its onTap entity to select date and time via functions.

Exploring Date and Time Pickers

For the sake of simplicity, we will be having StatefulWidget for both to handle them better.

Firstly, we need to create a TextEdittingController for both and assign them to their respective fields.

  • Consider this code snippet
// Date
CustomFormField.rounded(
  controller: _datePickerController,
  hintText: "Tap to select Date",
  readOnly: true,
  onChanged: (val) {},
  onTap: () => datePickerDialog(context),
),

// Time
Container(
  margin: const EdgeInsets.only(top: 10),
  child: CustomFormField.rounded(
    controller: _timePickerController,
    hintText: "Tap to select Time",
    readOnly: true,
    onChanged: (val) {},
    onTap: () => timePickerDialog(context),
  ),
),

1- Date Picker

Once we get through the above steps, let’s create two functions for date and time dialog pickers.

  • Here’s the code snippet
dynamic datePickerDialog(BuildContext context) async {
    var date = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(1980),
        lastDate: DateTime(2030));

    if (date != null) {
      setState(() {
        _datePickerController.text = date.toString();
      });
    }
  }

2- Time Picker

dynamic timePickerDialog(BuildContext context) async {
var time = await showTimePicker(context: context, initialTime: TimeOfDay.now());

if (time != null) {
setState(() {
_timePickerController.text = time.format(context);
});
}
}

Here, our initial setup is completed. It’s time to run the app.

UI View

After receiving a successful response, one thing that needs to be addressed here is, that the snapshot says it all, i.e. formatting of date is necessary as it can’t be counted as good practice according to an end-user perspective.

Well, we have certain ways for that, which are as follows:

— Method 1

* Intl Package

Head over to pub.dev and install this package

——OR—–

Jot down this command under the project’s terminal

flutter pub add intl

https://pub.dev/packages/intl

After installation, import the package and use it like:

dynamic datePickerDialog(BuildContext context) async {
    var date = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(1980),
        lastDate: DateTime(2030));

    if (date != null) {

      // Create a new variable for DateFormat (package)
        String convertDate = DateFormat.yMd().format(date); 

      setState(() {
        _datePickerController.text = convertDate;
      });
    }
  }

Apart from this, there is a better and more efficient way to produce the same output with the help of Flutter Extensions.

— Method 2

* Extensions

A Flutter Extension adds functionality to the existing libraries. Moreover, the creative part of this is, that we unknowingly use them repeatedly.

Here’s a sample snippet displaying the unknown use of extensions.

"Test String".toUpperCase();
"Test".replaceAll("/$", "");

Here is the sample format:

extension ExtensionTitle on runtimeType {
  /* getter function */
}

Now, as in our case, we need to have a getter function that would return to the appropriate date format based on the date provided.

So, our above extension function would look something like this:

import 'package:intl/intl.dart';

extension DateExtension on DateTime {
  String get formattedDate => DateFormat.yMd().format(this);
}

Now, our DatePickerDialog function will look like this:

dynamic datePickerDialog(BuildContext context) async {
    var date = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(1980),
        lastDate: DateTime(2030));

    if (date != null) {

      // Create a new variable for DateFormat (package)
        String convertDate = DateFormat.yMd().format(date); 

      setState(() {
        _datePickerController.text = date.formattedDate; /* automatic suggession */
      });
    }
  }

Note: It’s better to restart the app to avoid any crashes.

Converted Date Snapshot

Date and Time displayed

Theming Date & Time Picker Dialogs

Apart from this stuff, we can apply styling/theming to these pickers per our project’s theme structure or random colors. We need to take the builder entity into account, such as:

Styling Date Picker

builder: (context, child) {
  return Theme(
    data: ThemeData.dark().copyWith(
      colorScheme: const ColorScheme.dark(
        primary: Colors.black, // Date indicator
        onPrimary: Colors.white, // Text Color
        surface: Colors.black, // Top Color
        onSurface: Colors.white, // Top Text Color
      ),
      dialogBackgroundColor: Colors.blue[800],
    ),
    child: child!,
  );
},

// We can also select the date and entry mode for date picker by making use of
      initialDatePickerMode: DatePickerMode.day,
      initialEntryMode: DatePickerEntryMode.calendarOnly,

UI Snapshot

Date picker theme

Styling Time Picker

  dynamic timePickerDialog(BuildContext context) async {
    var time = await showTimePicker(context: context, initialTime: 
     TimeOfDay.now(),
      builder: (context, child) {
        return Theme(
          data: ThemeData.dark().copyWith(
            colorScheme: const ColorScheme.dark(
              primary: Colors.white, // Date indicator
              onPrimary: Colors.white, // Text Color
              surface: Colors.black, // Top Color
              onSurface: Colors.white, // Top Text Color
            ),
            dialogBackgroundColor: Colors.blue[800],
          ),
          child: child!,
        );
      },
    );

    if (time != null) {
      setState(() {
        _timePickerController.text = time.format(context);
      });
    }
  }

UI Snapshot

Time picker theme

Furthermore, other additional Date and Time picker dialog minor entities need attention, so let’s explore them as well.

— Applying Locale to Pickers

Flutter, by default, supports only US localizations. However, to add variety, an application must use other Material or Cupertino properties, vis-à-vis including a package flutter_localizations, under dev_dependencies.

Here’s the appropriate format:

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

Instead, there’s a better way of doing this, by using an in-build command:

flutter pub add flutter_localizations --sdk=flutter

After installation, head over to the file where MaterialApp is being returned.

We need to apply some configurations regarding the use of certain locales (language prefixes).

Here is the code snippet:

 return MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('en'),
        Locale('ur'),
      ],
      debugShowCheckedModeBanner: false,
      home: PickersDemo(),
    );

For now, besides English, I have added the Urdu locale as well.

Note: There’s no limitation on how many locales there can be. Moreover, we must know the exact locale prefix to avoid any app crash event.

Head over to the Date picker dialog file and apply this locale in the following format:

showDatePicker(
      context: context,
      initialDate: DateTime.now(),
      locale: Locale('ur'),
      firstDate: DateTime(1980),
      lastDate: DateTime(2030),
      initialDatePickerMode: DatePickerMode.day,
      initialEntryMode: DatePickerEntryMode.calendarOnly,
    );

Note: Don’t forget to quit and restart the app to avoid any issues.

It’s time to test our App.

UI Snapshot

Date picker with Urdu locale

Apart from this, we can also customize the various texts associated with Date and Time Pickers with the help of the following entities listed:

String? helpText,
String? cancelText,
String? confirmText,
String? errorFormatText,
String? errorInvalidText,
String? fieldHintText,
String? fieldLabelText,

Furthermore, for an in-depth explanation, I have attached this tutorial.

Additionally, you can learn about other properties of these two pickers from the official documentation itself.

It’s time to wind up this blog post.

Thank you so much for your participation and of course your precious time.


Summing Up

Wrapping it up, we learned about Date and Time pickers in Flutter, styling them, modifying their formats via external packages, etc. Hope you enjoy reading this one.

However, If you think something was left out or incomplete, you can jot it down in the comments section below. I would love to respond to that.

You can get the source code from this GitHub Repository.

Also, check out my YouTube handle, as it contains tons of content regarding Flutter itself & GitHub.

Link to other blog posts

Also read – Flutter Easy Localization – Adding Extra Efficiency to Flutter Apps

Leave a Comment