diff --git a/examples/api/lib/cupertino/date_picker/cupertino_date_picker.0.dart b/examples/api/lib/cupertino/date_picker/cupertino_date_picker.0.dart new file mode 100644 index 0000000000..2763ae2408 --- /dev/null +++ b/examples/api/lib/cupertino/date_picker/cupertino_date_picker.0.dart @@ -0,0 +1,186 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flutter code sample for CupertinoDatePicker + +import 'package:flutter/cupertino.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + static const String _title = 'Flutter Code Sample'; + + @override + Widget build(BuildContext context) { + return const CupertinoApp( + title: _title, + home: MyStatelessWidget(), + ); + } +} + +class MyStatelessWidget extends StatefulWidget { + const MyStatelessWidget({Key? key}) : super(key: key); + + @override + State createState() => _MyStatelessWidgetState(); +} + +class _MyStatelessWidgetState extends State { + DateTime date = DateTime(2016, 10, 26); + DateTime time = DateTime(2016, 5, 10, 22, 35); + DateTime dateTime = DateTime(2016, 8, 3, 17, 45); + + // This shows a CupertinoModalPopup with a reasonable fixed height which hosts CupertinoDatePicker. + void _showDialog(Widget child) { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) => Container( + height: 216, + padding: const EdgeInsets.only(top: 6.0), + // The Bottom margin is provided to align the popup above the system navigation bar. + margin: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom, + ), + // Provide a background color for the popup. + color: CupertinoColors.systemBackground.resolveFrom(context), + // Use a SafeArea widget to avoid system overlaps. + child: SafeArea( + top: false, + child: child, + ), + ) + ); + } + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + child: DefaultTextStyle( + style: TextStyle( + color: CupertinoColors.label.resolveFrom(context), + fontSize: 22.0, + ), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _DatePickerItem( + children: [ + const Text('Date'), + CupertinoButton( + // Display a CupertinoDatePicker in date picker mode. + onPressed: () => _showDialog( + CupertinoDatePicker( + initialDateTime: date, + mode: CupertinoDatePickerMode.date, + use24hFormat: true, + // This is called when the user changes the date. + onDateTimeChanged: (DateTime newDate) { + setState(() => date = newDate); + }, + ), + ), + // In this example, the date value is formatted manually. You can use intl package + // to format the value based on user's locale settings. + child: Text('${date.month}-${date.day}-${date.year}', + style: const TextStyle( + fontSize: 22.0, + ), + ), + ), + ], + ), + _DatePickerItem( + children: [ + const Text('Time'), + CupertinoButton( + // Display a CupertinoDatePicker in time picker mode. + onPressed: () => _showDialog( + CupertinoDatePicker( + initialDateTime: time, + mode: CupertinoDatePickerMode.time, + use24hFormat: true, + // This is called when the user changes the time. + onDateTimeChanged: (DateTime newTime) { + setState(() => time = newTime); + }, + ), + ), + // In this example, the time value is formatted manually. You can use intl package to + // format the value based on the user's locale settings. + child: Text('${time.hour}:${time.minute}', + style: const TextStyle( + fontSize: 22.0, + ), + ), + ), + ], + ), + _DatePickerItem( + children: [ + const Text('DateTime'), + CupertinoButton( + // Display a CupertinoDatePicker in dateTime picker mode. + onPressed: () => _showDialog( + CupertinoDatePicker( + initialDateTime: dateTime, + use24hFormat: true, + // This is called when the user changes the dateTime. + onDateTimeChanged: (DateTime newDateTime) { + setState(() => dateTime = newDateTime); + }, + ), + ), + // In this example, time value is formatted manually. You can use intl package to + // format the value based on the user's locale settings. + child: Text('${dateTime.month}-${dateTime.day}-${dateTime.year} ${dateTime.hour}:${dateTime.minute}', + style: const TextStyle( + fontSize: 22.0, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} + +// This class simply decorates a row of widgets. +class _DatePickerItem extends StatelessWidget { + const _DatePickerItem({required this.children}); + + final List children; + + @override + Widget build(BuildContext context) { + return DecoratedBox( + decoration: const BoxDecoration( + border: Border( + top: BorderSide( + color: CupertinoColors.inactiveGray, + width: 0.0, + ), + bottom: BorderSide( + color: CupertinoColors.inactiveGray, + width: 0.0, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: children, + ), + ), + ); + } +} diff --git a/examples/api/test/cupertino/date_picker/cupertino_date_picker.0_test.dart b/examples/api/test/cupertino/date_picker/cupertino_date_picker.0_test.dart new file mode 100644 index 0000000000..af9a22bee1 --- /dev/null +++ b/examples/api/test/cupertino/date_picker/cupertino_date_picker.0_test.dart @@ -0,0 +1,67 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_api_samples/cupertino/date_picker/cupertino_date_picker.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +const Offset _kRowOffset = Offset(0.0, -50.0); + +void main() { + testWidgets('Can change date, time and dateTime using CupertinoDatePicker', (WidgetTester tester) async { + await tester.pumpWidget( + const example.MyApp(), + ); + // Open the date picker. + await tester.tap(find.text('10-26-2016')); + await tester.pumpAndSettle(); + + // Drag month, day and year wheels to change the picked date. + await tester.drag(find.text('October'), _kRowOffset, touchSlopY: 0, warnIfMissed: false); // see top of file + await tester.drag(find.text('26'), _kRowOffset, touchSlopY: 0, warnIfMissed: false); // see top of file + await tester.drag(find.text('2016'), _kRowOffset, touchSlopY: 0, warnIfMissed: false); // see top of file + + await tester.pump(); + await tester.pump(const Duration(milliseconds: 500)); + + // Close the date picker. + await tester.tapAt(const Offset(1.0, 1.0)); + await tester.pumpAndSettle(); + + expect(find.text('12-28-2018'), findsOneWidget); + + // Open the time picker. + await tester.tap(find.text('22:35')); + await tester.pumpAndSettle(); + + // Drag hour and minute wheels to change the picked time. + await tester.drag(find.text('22'), const Offset(0.0, 50.0), touchSlopY: 0, warnIfMissed: false); // see top of file + await tester.drag(find.text('35'), const Offset(0.0, 50.0), touchSlopY: 0, warnIfMissed: false); // see top of file + + await tester.pump(); + await tester.pump(const Duration(milliseconds: 500)); + + // Close the time picker. + await tester.tapAt(const Offset(1.0, 1.0)); + await tester.pumpAndSettle(); + + expect(find.text('20:33'), findsOneWidget); + + // Open the dateTime picker. + await tester.tap(find.text('8-3-2016 17:45')); + await tester.pumpAndSettle(); + + // Drag hour and minute wheels to change the picked time. + await tester.drag(find.text('17'), const Offset(0.0, 50.0), touchSlopY: 0, warnIfMissed: false); // see top of file + await tester.drag(find.text('45'), const Offset(0.0, 50.0), touchSlopY: 0, warnIfMissed: false); // see top of file + + await tester.pump(); + await tester.pump(const Duration(milliseconds: 500)); + + // Close the dateTime picker. + await tester.tapAt(const Offset(1.0, 1.0)); + await tester.pumpAndSettle(); + + expect(find.text('8-3-2016 15:43'), findsOneWidget); + }); +} diff --git a/packages/flutter/lib/src/cupertino/date_picker.dart b/packages/flutter/lib/src/cupertino/date_picker.dart index eaadaf8303..9c1eae8096 100644 --- a/packages/flutter/lib/src/cupertino/date_picker.dart +++ b/packages/flutter/lib/src/cupertino/date_picker.dart @@ -202,6 +202,16 @@ enum _PickerColumnType { /// full screen width. Content texts are shown with /// [CupertinoTextThemeData.dateTimePickerTextStyle]. /// +/// {@tool dartpad} +/// This sample shows how to implement CupertinoDatePicker with different picker modes. +/// We can provide intiial dateTime value for the picker to display. When user changes +/// the drag the date or time wheels, the picker will call onDateTimeChanged callback. +/// +/// CupertinoDatePicker can be displayed directly on a screen or in a popup. +/// +/// ** See code in examples/api/lib/cupertino/date_picker/cupertino_date_picker.0.dart ** +/// {@end-tool} +/// /// See also: /// /// * [CupertinoTimerPicker], the class that implements the iOS-style timer picker.