iosflutterwidgetcupertinopicker

Flutter - CupertinoDatePicker initialDateTime updates only once


I've created a CupertinoDatePicker widget, with an initial value set to a variable.

I want to update the selected value in the picker to that variable value when the user clicks on another widget in the screen - but it doesn't work (although the CupertinoDatePicker widget gets rebuilt).

Is it a bug or am I doing something wrong?

Code (can be copy-pasted into dartPad):

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
final _time = DateTime.now();
int _min = 5;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  createState() => MyWidgetSate();
}

class MyWidgetSate extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('_min = ' + _min.toString(), style: Theme.of(context).textTheme.headline4),
        _buildDurationPicker(context),
        RaisedButton(
            onPressed: () {
              print('hello');
              setState(() {
                _min += 5;
              });
            },
            child: const Text('Add', style: TextStyle(fontSize: 20)),
          ),
        ],
    );
  }
}

Widget _buildDurationPicker(BuildContext context) {
    DateTime initDateTime = DateTime(_time.year, _time.month, _time.day)
        .add(Duration(minutes: _min));
    return Container(
      height: 216.0,
      color: Colors.white,
      child: CupertinoDatePicker(
        mode: CupertinoDatePickerMode.time,
        use24hFormat: true,
        initialDateTime: initDateTime,
        backgroundColor: Colors.transparent,
        onDateTimeChanged: (DateTime date) {
          //
        },
      ),
    );
  }

Solution

  • CupertinoDatePicker is maintaining state internally and only set the initialDateTime on its initState, despite you updating your widget's state.

    To force a rebuild each time you set your initialDateTime, assign an UniqueKey() as a key of your CupertinoDatePicker and it will rebuild every time your state changes with a new initDateTime.

    (...)
      CupertinoDatePicker(
            key: UniqueKey(),
            mode: CupertinoDatePickerMode.time,
            use24hFormat: true,
            initialDateTime: initDateTime,
            backgroundColor: Colors.transparent,
            onDateTimeChanged: (DateTime date) {
              //
            },
          ),