Repository navigation
Unexpected showDatePicker behavior when changing year #81547
Description
Activity
- addedf: date/time pickerDate or time picker widgetsDate or time picker widgetsp: material_uimaterial_ui package in flutter/packagesmaterial_ui package in flutter/packagesframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.
on Apr 30, 2021 @HansMuller @darrenaustin Having shipped this to real users, I can confirm that this is extremely confusing in practice. We have lots of users entering the wrong date by mistake.
I would consider this a dire usability issue in an extremely popular component. I can see that others have reported this issue and I would be surprised if there is any Flutter app that uses this component for inputting, say, a user's birthday that isn't having many users select the wrong date by mistake.
It turns out that it is an extremely common user behavior to select the month and day first, and then change the year. In the native Android date picker this works as expected, but in Flutter the user will select the wrong year.
To drive home how big a problem this is, we
are considering switchinghave switched to the Cupertino date picker even for our Android users.Reacted by Felix Angelov, David King, Nathan Chau and LexyconHi @jjoelson
Thanks for filing the issueminimal code sample
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', theme: ThemeData.dark(), home: Home(), ); } } class Home extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Center( child: Container( child: Text('Hello World'), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () async { showDatePicker( context: context, initialDate: DateTime(2021, 4, 30), firstDate: DateTime(2000), lastDate: DateTime(2030), ); }, ), ); } }
stablemaster❗️ ❗️ Check
flutter doctor -voutputs for each channel belowflutter doctor -v
[✓] Flutter (Channel stable, 2.5.2, on macOS 12.0 21A5534d darwin-x64, locale en-GB) • Flutter version 2.5.2 at /Users/tahatesser/Code/flutter_stable • Upstream repository https://github.com/flutter/flutter.git • Framework revision 3595343e20 (17 hours ago), 2021-09-30 12:58:18 -0700 • Engine revision 6ac856380f • Dart version 2.14.3 [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) • Android SDK at /Users/tahatesser/Code/SDK • Platform android-30, build-tools 29.0.2 • ANDROID_HOME = /Users/tahatesser/Code/SDK • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 13.0, Build version 13A233 • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2020.3) • Android Studio at /Applications/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 11.0.10+0-b96-7281165) [✓] VS Code (version 1.60.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.26.0 [✓] Connected device (3 available) • Redmi K20 Pro (mobile) • def0ad20 • android-arm64 • Android 11 (API 30) • macOS (desktop) • macos • darwin-x64 • macOS 12.0 21A5534d darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 94.0.4606.61 • No issues found!
[✓] Flutter (Channel master, 2.6.0-12.0.pre.167, on macOS 12.0 21A5534d darwin-x64, locale en-GB) • Flutter version 2.6.0-12.0.pre.167 at /Users/tahatesser/Code/flutter_master • Upstream repository https://github.com/flutter/flutter.git • Framework revision 50604c614e (7 hours ago), 2021-09-30 23:18:02 -0700 • Engine revision aed327b84d • Dart version 2.15.0 (build 2.15.0-168.0.dev) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) • Android SDK at /Users/tahatesser/Code/SDK • Platform android-30, build-tools 29.0.2 • ANDROID_HOME = /Users/tahatesser/Code/SDK • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 13.0) • Xcode at /Applications/Xcode.app/Contents/Developer • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2020.3) • Android Studio at /Applications/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 11.0.10+0-b96-7281165) [✓] VS Code (version 1.60.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.26.0 [✓] Connected device (3 available) • Redmi K20 Pro (mobile) • def0ad20 • android-arm64 • Android 11 (API 30) • macOS (desktop) • macos • darwin-x64 • macOS 12.0 21A5534d darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 94.0.4606.61 • No issues found!
✅: No Issue ❗️: Issue reproduced
- addedfound in release: 2.5Found to occur in 2.5Found to occur in 2.5found in release: 2.6Found to occur in 2.6Found to occur in 2.6has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work on
on Oct 1, 2021 It turns out that it is an extremely common user behavior to select the month and day first, and then change the year. In the native Android date picker this works as expected, but in Flutter the user will select the wrong year.
I just tested this behavior, if you set the initial date and go to 2015, it still returns
4/30/2021(which matches Flutter behavior). if you omit the initial date, "okay" is not active, forcing the user to choose a date when scrolling back to 2015minimal code sample
package com.tahatesser.myapplication import android.os.Bundle import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.FragmentManager import androidx.navigation.fragment.findNavController import com.google.android.material.datepicker.CalendarConstraints import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import com.tahatesser.myapplication.databinding.FragmentFirstBinding import java.util.* /** * A simple [Fragment] subclass as the default destination in the navigation. */ class FirstFragment : Fragment() { private var _binding: FragmentFirstBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = FragmentFirstBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.datePickerButton.setOnClickListener { val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")) calendar.set(2015,0,1) val startdDate = calendar.timeInMillis calendar.set(2021,3,30) val endDate = calendar.timeInMillis val constraintsBuilder = CalendarConstraints.Builder() .setStart(startdDate) .setEnd(endDate) val materialTimePicker = MaterialDatePicker.Builder.datePicker() .setTitleText("Select dates") .setSelection(endDate) .setCalendarConstraints(constraintsBuilder.build()) .build() materialTimePicker.addOnPositiveButtonClickListener { Log.d("materialTimePicker", "${materialTimePicker.selection}") } val supportFragmentManager = this.childFragmentManager.beginTransaction() materialTimePicker.show(supportFragmentManager, "fragment_tag") } } override fun onDestroyView() { super.onDestroyView() _binding = null } }
Screen.Recording.2021-10-13.at.2.02.34.PM.mov
It returns
1619740800000which isApril 30, 2021- addedwaiting for responseThe Flutter team cannot make further progress on this issue until the original reporter respondsThe Flutter team cannot make further progress on this issue until the original reporter responds
on Oct 13, 2021 Hi @TahaTesser, thanks for looking into this!
I am not an Android developer or user, so I'm not terribly surprised to find that my information about the native material picker is incorrect 😅. When I created this issue, I created a simple HTML date input, assuming that Chrome uses the native material date picker:
Android.-.Date.Picker.mov
So with the native picker's behavior acknowledged, we still have a major usability issue on our hands here, even if it's not exclusive to Flutter's Material implementation.
If you go to the Material date picker documentation and scroll down to the video captioned with "Tapping the year menu accesses the year picker. Scrolling vertically navigates across years", you'll see that changing the year from 2018 to 2016 also changes the selected date: direct video link
Obviously that video is just a mockup, but it seems possible to me that the intended design here is for the date to change when the year changes. Is it possible that in replicating the native Material date picker component, Flutter has also replicated a bug in that component?
if you omit the initial date, "okay" is not active, forcing the user to choose a date when scrolling back to 2015
This is a smaller issue, but Flutter's Material date picker doesn't allow you to omit
initialDatein order to disable the "OK" button as far as I can tell.Reacted by Taha Tesser and Vishesh Handa- removedwaiting for responseThe Flutter team cannot make further progress on this issue until the original reporter respondsThe Flutter team cannot make further progress on this issue until the original reporter responds
on Oct 13, 2021 @jjoelson
Thanks for the quick response, this really helps.Reacted by Jonathan JoelsonWhile the design video clearly shows that is not working as expected but even Android 12 doesn't have match the behavior. This is a breaking change, most people will compare the flutter calendar with the native android calendar, and might think this is odd. So I can't move forward with this for now
cc: @darrenaustin
Still experiencing this issue in May 2022. Are there any updates/fixes?
- addedteam-designOwned by Design Languages teamOwned by Design Languages teamtriaged-designTriaged by Design Languages teamTriaged by Design Languages team
on Jul 8, 2023 - added a commit that references this issue
on Jul 24, 2023 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 -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Aug 7, 2023
It's not clear if this is a bug or intended behavior, but at any rate the Flutter Material date picker has a behavior that differs from that of the native Android date picker in such a way that is likely to cause users accustomed to the native behavior to select the wrong date in a Flutter app.
Steps to Reproduce
showDatePickerwithinitialDate: DateTime(2021, 4, 30)Expected results:
4/30/2015 ought to be the newly selected date i.e. the month/day in the newly selected year that corresponds to that of the previously selected date (or closest available).
Actual results:
The date picker displays April in 2015, but 4/30/2021 remains the selected date. If the user taps OK at this point intending to select 4/30/2015 then they will actually select 4/30/2021.
RPReplay_Final1619795575.MP4
Logs