Skip to content

Cupertino date picker does not work correctly when using minuteInterval and scrolling past the endDate #97010

Closed

Description

@ansolantz

Steps to Reproduce

The Cupertino date picker does not work correctly when using minuteInterval and scrolling past the endDate

What happens: In the attached example, when scrolling past the end time of 40 minutes, it scrolls back to minute 20.

Expected: If endDate is at minute 40 and I scroll to minute 45, it should scroll back to 40.
The reason is that the scroll controller does not take the minuteInterval into account when scrolling back.

I have opened a PR here.

Code sample
class _MyHomePageState extends State<MyHomePage> {
  DateTime? selectedDate;
  DateTime now = DateTime.now();
  late DateTime startDate = DateTime(now.year, now.month, now.day, 0, 5, 0);
  late DateTime endDate = DateTime(now.year, now.month, now.day, 19, 40, 0);

  int minuteInterval = 5;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Cupertino DatePicker"),
      ),
      body: Container(
        margin: EdgeInsets.all(40),
        width: double.infinity,
        height: MediaQuery.of(context).size.height * 0.25,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(
              child: Text("Show DatePicker"),
              onPressed: () {
                showDatePicker();
              },
            ),
            Text(selectedDate == null ? "" : "$selectedDate")
          ],
        ),
      ),
    );
  }

  void showDatePicker() {
    showCupertinoModalPopup(
      context: context,
      builder: (BuildContext builder) {
        return Container(
          height: MediaQuery.of(context).copyWith().size.height * 0.30,
          color: Colors.white,
          child: CupertinoDatePicker(
            initialDateTime: _adjustDateTime(DateTime.now()),
            onDateTimeChanged: (newDate) {},
            use24hFormat: false,
            minuteInterval: minuteInterval,
            minimumDate: _adjustDateTime(startDate),
            maximumDate: _adjustDateTime(endDate),
            mode: CupertinoDatePickerMode.dateAndTime,
          ),
        );
      },
    );
  }

  DateTime? _adjustDateTime(DateTime? date) {
    return date == null
        ? null
        : DateTime(date.year, date.month, date.day, date.hour,
            date.minute - (date.minute % minuteInterval), 0, 0, 0);
  }
Logs
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel unknown, 2.9.0-1.0.pre.433, on macOS 11.5.2 20G95 darwin-arm, locale en-ES)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.63.2)
[✓] VS Code (version 1.64.0-insider)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

Activity

  1. darshankawar commented on Jan 24, 2022

    @darshankawar
    Member

    @ansolantz
    Thanks for the report and potential fix, but I ran your code sample using latest master but was unable to replicate the behavior. Are there are specific steps to replicate ?

    97010.mov

    Flutter (Channel master, 2.9.0-1.0.pre.463)

  2. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 24, 2022
  3. ansolantz commented on Jan 24, 2022

    @ansolantz
    Author

    Hi @darshankawar,
    Thanks for your reply! I'm sorry, I did not describe it clear enough. The issue occurs when you scroll past the maximumDate, in my example I put today at 19:40 (7:40 PM) as endDate. Then, instead of scrolling back to 40 minutes, it scrolls back to minute 20. You also need to set the minuteInterval larger than 1 (in my case I use 5).

    cupertino-date-picker-issue.mov
  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 24, 2022
  5. darshankawar commented on Jan 25, 2022

    @darshankawar
    Member

    Thanks for the update. Using above explaination, I do see the same behavior, ie, the minuteInterval doesn't reset to most recent value but defaults to 20 once it goes past the endDate:

    97010.mov
    master, stable flutter doctor -v
    
    [✓] Flutter (Channel master, 2.9.0-1.0.pre.491, on Mac OS X 10.15.4 19E2269
        darwin-x64, locale en-GB)
        • Flutter version 2.9.0-1.0.pre.491 at
          /Users/dhs/documents/fluttersdk/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 7ec334827a (2 hours ago), 2022-01-24 19:50:10 -0800
        • Engine revision 83cfdcc8f1
        • Dart version 2.17.0 (build 2.17.0-51.0.dev)
        • DevTools version 2.9.2
    
    [!] Xcode - develop for iOS and macOS (Xcode 12.3)
        • Xcode at /Applications/Xcode.app/Contents/Developer
        ! Flutter recommends a minimum Xcode version of 13.
          Download the latest version or update via the Mac App Store.
        • CocoaPods version 1.11.2
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] VS Code (version 1.62.0)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.21.0
    
    [✓] Connected device (2 available)
        • macOS (desktop) • macos  • darwin-x64     • Mac OS X 10.15.4 19E2269
          darwin-x64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 97.0.4692.99
    
    [✓] HTTP Host Availability
        • All required HTTP hosts are available
    
    ! Doctor found issues in 1 category.
    
    [✓] Flutter (Channel stable, 2.8.1, on Mac OS X 10.15.4 19E2269 darwin-x64,
        locale en-GB)
        • Flutter version 2.8.1 at /Users/dhs/documents/fluttersdk/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 77d935af4d (13 hours ago), 2021-12-16 08:37:33 -0800
        • Engine revision 890a5fca2e
        • Dart version 2.15.1
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 30)
        • Android SDK at /Users/dhs/Library/Android/sdk
        • Platform android-30, build-tools 30.0.3
        • ANDROID_HOME = /Users/dhs/Library/Android/sdk
        • Java binary at: /Users/dhs/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android
          Studio.app/Contents/jre/jdk/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
        • All Android licenses accepted.    
    
    [✓] Xcode - develop for iOS and macOS
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Xcode 12.3, Build version 12C33
        • CocoaPods version 1.10.1
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 4.1)
        • Android Studio at /Users/dhs/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android
          Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build
          1.8.0_242-release-1644-b3-6915495)        
    
    [✓] VS Code (version 1.57.1)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.21.0
    
    [✓] Connected device (4 available)
        • Darshan's iphone (mobile)  • 21150b119064aecc249dfcfe05e259197461ce23 •
          ios            • iOS 14.4.1 18D61
        • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729     •
          ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
        • macOS (desktop)            • macos                                    •
          darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
        • Chrome (web)               • chrome                                   •
          web-javascript • Google Chrome 93.0.4577.82
    
    
    • No issues found!
    
    
    complete code sample
    
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            // This is the theme of your application.
            //
            // Try running your application with "flutter run". You'll see the
            // application has a blue toolbar. Then, without quitting the app, try
            // changing the primarySwatch below to Colors.green and then invoke
            // "hot reload" (press "r" in the console where you ran "flutter run",
            // or press Run > Flutter Hot Reload in IntelliJ). Notice that the
            // counter didn't reset back to zero; the application is not restarted.
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key? key, required this.title}) : super(key: key);
    
      // This widget is the home page of your application. It is stateful, meaning
      // that it has a State object (defined below) that contains fields that affect
      // how it looks.
    
      // This class is the configuration for the state. It holds the values (in this
      // case the title) provided by the parent (in this case the App widget) and
      // used by the build method of the State. Fields in a Widget subclass are
      // always marked "final".
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      DateTime? selectedDate;
      DateTime now = DateTime.now();
      late DateTime startDate = DateTime(now.year, now.month, now.day, 0, 5, 0);
      late DateTime endDate = DateTime(now.year, now.month, now.day, 19, 40, 0);
    
      int minuteInterval = 5;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Flutter Cupertino DatePicker"),
          ),
          body: Container(
            margin: EdgeInsets.all(40),
            width: double.infinity,
            height: MediaQuery
                .of(context)
                .size
                .height * 0.25,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  child: Text("Show DatePicker"),
                  onPressed: () {
                    showDatePicker();
                  },
                ),
                Text(selectedDate == null ? "" : "$selectedDate")
              ],
            ),
          ),
        );
      }
    
      void showDatePicker() {
        showCupertinoModalPopup(
          context: context,
          builder: (BuildContext builder) {
            return Container(
              height: MediaQuery
                  .of(context)
                  .copyWith()
                  .size
                  .height * 0.30,
              color: Colors.white,
              child: CupertinoDatePicker(
                initialDateTime: _adjustDateTime(DateTime.now()),
                onDateTimeChanged: (newDate) {},
                use24hFormat: false,
                minuteInterval: minuteInterval,
                minimumDate: _adjustDateTime(startDate),
                maximumDate: _adjustDateTime(endDate),
                mode: CupertinoDatePickerMode.dateAndTime,
              ),
            );
          },
        );
      }
    
      DateTime? _adjustDateTime(DateTime? date) {
        return date == null
            ? null
            : DateTime(
            date.year,
            date.month,
            date.day,
            date.hour,
            date.minute - (date.minute % minuteInterval),
            0,
            0,
            0);
      }
    }
    
    
  6. added
    p: cupertino_uicupertino_ui package in flutter/packages
    frameworkflutter/packages/flutter repository. See also f: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    and removed
    in triagePresently being triaged by the triage team
    on Jan 25, 2022
  7. NikosTsesmelis commented on Mar 3, 2022

    @NikosTsesmelis
    Contributor

    Is there any progress with this? We cannot use minimumDate and maximumDate with minuteInterval and we need this to upload.

  8. NikosTsesmelis commented on May 30, 2022

    @NikosTsesmelis
    Contributor

    This is not fixed yet in flutter 3.1.

  9. darshankawar commented on May 30, 2022

    @darshankawar
    Member

    @NikosTsesmelis
    The issue is still open and not assigned yet. There's a PR opened by OP but seem to need tests to progress further.

  10. Hixie commented on May 31, 2022

    @Hixie
    Contributor

    PR #97012 was written to fix this bug but unfortunately it was not completed (it just needed tests) so the PR has been closed. If anyone would like to start from that PR and apply the review comments and drive this PR to completion, you are definitely welcome to do so!

  11. NikosTsesmelis commented on Jun 21, 2022

    @NikosTsesmelis
    Contributor

    I have opened this pr for over a week now and there is no answer. Have I missed something because I have not done this again?

  12. Hixie commented on Jun 24, 2022

    @Hixie
    Contributor

    @NikosTsesmelis Our bad, sorry about that. Let me see if I can find out why it wasn't noticed during triage.

  13. Hixie commented on Jul 11, 2022

    @Hixie
    Contributor

    Sorry for the continued delay.

  14. TahaTesser commented on Jul 21, 2022

    @TahaTesser
    Contributor

    #105958 landed

  15. added
    r: fixedIssue is closed as already fixed in a newer version
    on Jul 21, 2022
  16. github-actions commented on Aug 4, 2022

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  17. locked as resolved and limited conversation to collaborators on Aug 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    f: date/time pickerDate or time picker widgetsfound in release: 2.8Found to occur in 2.8found in release: 2.9Found to occur in 2.9frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: cupertino_uicupertino_ui package in flutter/packagesplatform-iosiOS applications specificallyr: fixedIssue is closed as already fixed in a newer version

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions