Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use 24 hour clock when invoking showTimePicker() in Flutter?

Tags:

flutter

dart

when I'm invoking method showTimePicker() in Fluter it shows me a picker with 12-hour clock (uses AM and PM periods). Also when I invoke format() method on TimeOfDay object it returns value in 12 hours system.

How do I change it to 24 hours clock? I've found that I need to change alwaysUse24HourFormat property in Window class but i have no idea how to do it.

Could anyone help me? Thank you in advance for your answers.

edit: code is shown below:

    Future<Null> _selectTime(BuildContext context) async {
    final TimeOfDay response = await showTimePicker(
      context: context,
      initialTime: pickedTime,
    );
    if (response != null && response != pickedTime) {
      setState(() {
        pickedTime = response;
      });
    }
  } 

edit2: i tried this only with Android.

like image 699
mbartn Avatar asked Aug 24 '18 10:08

mbartn


3 Answers

The above answers didn't work for me. Maybe for the new flutter or dart version. I fixed it by -

 final newTime = await showTimePicker(
        context: context,
        initialTime: TimeOfDay.now(),
        builder: (context, child) {
          return MediaQuery(
            data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
          child: child ?? Container(),
          );
        },
      );
like image 114
Gk Mohammad Emon Avatar answered Oct 07 '22 09:10

Gk Mohammad Emon


Before reading this answer, you need to know how MediaQuery.of() works. Essentially, there is a tree of widgets in any given page. The widgets each have a Context which you can think of as a node in the tree. When you call MediaQuery.of(context), it basically traces up the tree until it finds (or doesn't find) a MediaQuery widget, and then returns the data associated with the widget.

What you want to do is possible, but you have to be slightly careful about how you do it. See below for a minimal code example:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) =>
          MediaQuery(data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), child: child),
      home: new Container(
        color: Colors.white,
        child: Center(
          child: Builder(
            builder: (context) => FlatButton(
                  onPressed: () => showTimePicker(context: context, initialTime: TimeOfDay.now()),
                  child: Text("Show Time Picker"),
                ),
          ),
        ),
      ),
    );
  }
}

There are a couple of things of note here. First is that I'm creating a new MediaQueryData from the old one in the builder for MaterialApp. This is because you can't modify the properites of a MaterialQueryData.

The second is that I'm wrapping the child in the builder for MaterialApp with a new MediaQuery. This is necessary so that all 'pages' in the navigator (which is part of material app in this instance) read this new MediaQueryData with MediaQuery.of().

The third is that I use a Builder around the FlatButton. If I didn't do that, the context that it would be using would be the context of MyApp, rather than a context under the MaterialApp. If you made your own class to enclose the 'page', that wouldn't be necessary.

The MediaQuery has to be put where it is now, because if you make it within your 'page' (anywhere under the container), it won't actually be read by the TimePicker widget. This is because the TimePicker is actually inserting itself as the top element of the navigation stack which lives under the Navigator (and MaterialApp), rather than being embedded under your page. If this wasn't the case, it would be much more difficult to use a time picker.

I don't know that I did a very good job of explaining that, so here's a diagram:

MyApp  <------ Context (the one that would have been used without the builder)
  MaterialApp
    MediaQuery (from flutter)
      MediaQuery copy (that was made in the builder)
        Navigator (implicit - built as part of MaterialApp)
         |- Container
         |    Center
         |      Builder     <----\ Context (used to showTimePicker)
         |        FlatButton ----/ 
         \- TimePicker
like image 34
rmtmckenzie Avatar answered Oct 07 '22 09:10

rmtmckenzie


Taking in consideration @rmtmckenzie answer, you can actually simplify what he told you. You don't need to set the alwaysUse24HourFormat: true within your MyApp context.

This will do the trick

void inputTimeSelect() async {
    final TimeOfDay picked = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
      builder: (BuildContext context, Widget child) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
          child: child,
        );
      },
    );
}

And the widget tree can be whatever you want.

like image 23
Linesofcode Avatar answered Oct 07 '22 09:10

Linesofcode