Home > Software design >  Flutter app logic to cancell date and time picker dialog box at once
Flutter app logic to cancell date and time picker dialog box at once

Time:06-23

I am working on a flutter app where to show date and time picker. In the the third example I am trying to show how to pick date and time together, which is working fine. But what I want is when the user cancels the date picker dialog then the time picker should automatically get cancelled. But right now we have to do it seprately. For reference, you can see the problem in the image below. I need some help with the app logic to cancel the date & time picked at once.

Output

import 'package:flutter/material.dart';
    import 'package:intl/intl.dart';
    
    void main() {
      runApp(const DateTimePickerApp());
    }
    
    class DateTimePickerApp extends StatelessWidget {
      const DateTimePickerApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          debugShowCheckedModeBanner: false,
          home: TextScreen(),
        );
      }
    }
    
    class TextScreen extends StatefulWidget {
      const TextScreen({
        Key? key,
      }) : super(key: key);
    
      @override
      State<TextScreen> createState() => _TextScreenState();
    }
    
    class _TextScreenState extends State<TextScreen> {
      DateTime selectedDate = DateTime.now();
      TimeOfDay selectedTime = TimeOfDay.now();
      DateTime dateTime = DateTime.now();
      bool showDate = true;
      bool showTime = true;
      bool showDateTime = true;
    
      // Select for Date
      Future<DateTime> _selectDate(BuildContext context) async {
        final selected = await showDatePicker(
          context: context,
          initialDate: selectedDate,
          firstDate: DateTime(2000),
          lastDate: DateTime(2025),
        );
        if (selected != null && selected != selectedDate) {
          setState(() {
            selectedDate = selected;
          });
        }
        return selectedDate;
      }
    
    // Select for Time
      Future<TimeOfDay> _selectTime(BuildContext context) async {
        final selected = await showTimePicker(
          context: context,
          initialTime: selectedTime,
        );
        if (selected != null && selected != selectedTime) {
          setState(() {
            selectedTime = selected;
          });
        }
        return selectedTime;
      }
    
      // select date time picker
    
      Future _selectDateTime(BuildContext context) async {
        final date = await _selectDate(context);
        final time = await _selectTime(context);
    
        if (date == null) return;
    
        if (time == null) return;
        setState(() {
          dateTime = DateTime(
            date.year,
            date.month,
            date.day,
            time.hour,
            time.minute,
          );
        });
      }
    
      String getDate() {
        // ignore: unnecessary_null_comparison
        if (selectedDate == null) {
          return 'select date';
        } else {
          return DateFormat('MMM d, yyyy').format(selectedDate);
        }
      }
    
      String getDateTime() {
        // ignore: unnecessary_null_comparison
        if (dateTime == null) {
          return 'select date timer';
        } else {
          return DateFormat('yyyy-MM-dd HH:mm a').format(dateTime);
        }
      }
    
      String getTime(TimeOfDay tod) {
        final now = DateTime.now();
    
        final dt = DateTime(now.year, now.month, now.day, tod.hour, tod.minute);
        final format = DateFormat.jm();
        return format.format(dt);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('GeeksforGeeks'),
            centerTitle: true,
            backgroundColor: Colors.green,
          ),
          body: Center(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                showDate ? Center(child: Text(getDate())) : const SizedBox(),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 15),
                  child: ElevatedButton(
                    onPressed: () {
                      _selectDate(context);
                      showDate = true;
                    },
                    child: const Text('Date Picker'),
                  ),
                ),
                showTime
                    ? Center(child: Text(getTime(selectedTime)))
                    : const SizedBox(),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 15),
                  child: ElevatedButton(
                    onPressed: () {
                      _selectTime(context);
                      showTime = true;
                    },
                    child: const Text('Timer Picker'),
                  ),
                ),
                showDateTime
                    ? Center(child: Text(getDateTime()))
                    : const SizedBox(),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 15),
                  child: ElevatedButton(
                    onPressed: () {
                      _selectDateTime(context);
                      showDateTime = true;
                    },
                    child: const Text(' Date & Time '),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }

CodePudding user response:

You need to use nullable selectedDate

class _TextScreenState extends State<TextScreen> {
  DateTime? selectedDate ;

then make _selectDate nullable return

  // Select for Date
  Future<DateTime?> _selectDate(BuildContext context) async {
    final selected = await showDatePicker(
      context: context,
      initialDate: selectedDate??DateTime.now(),
      firstDate: DateTime(2000),
      lastDate: DateTime(2025),
    );
    if (selected != null && selected != selectedDate) {
      setState(() {
        selectedDate = selected;
      });
    }
    return selectedDate;
  }

And while showing _selectTime check selectedDate if it null or not. Also make it null again if you like to avoid cancel second timer loop

  // select date time picker
  Future<void> _selectDateTime(BuildContext context) async {
    final date = await _selectDate(context);
    if (date == null) return;
    selectedDate = null; // if you want to avoid second loop time picker on cancel
    final time = await _selectTime(context);

You also need to add bang on getDate while selectedDate is now nullable. Using bang! because we've check it's null

String getDate() {
  // ignore: unnecessary_null_comparison
  if (selectedDate == null) {
    return 'select date';
  } else {
    return DateFormat('MMM d, yyyy').format(selectedDate);
  }
}
  • Related