Commit 2a8e35cc authored by Viet Do's avatar Viet Do Committed by xster

Cupertino Date Picker (#21251)

parent efc5123d
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../../gallery/demo.dart';
import 'cupertino_navigation_demo.dart' show coolColorNames;
......@@ -22,6 +23,15 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
Duration timer = Duration();
// Value that is shown in the date picker in date mode.
DateTime date = DateTime.now();
// Value that is shown in the date picker in time mode.
DateTime time = DateTime.now();
// Value that is shown in the date picker in dateAndTime mode.
DateTime dateTime = DateTime.now();
Widget _buildMenu(List<Widget> children) {
return Container(
decoration: const BoxDecoration(
......@@ -53,30 +63,10 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
);
}
Widget _buildColorPicker() {
final FixedExtentScrollController scrollController =
FixedExtentScrollController(initialItem: _selectedColorIndex);
return CupertinoPicker(
scrollController: scrollController,
itemExtent: _kPickerItemHeight,
backgroundColor: CupertinoColors.white,
onSelectedItemChanged: (int index) {
setState(() {
_selectedColorIndex = index;
});
},
children: List<Widget>.generate(coolColorNames.length, (int index) {
return Center(child:
Text(coolColorNames[index]),
);
}),
);
}
Widget _buildBottomPicker(Widget picker) {
return Container(
height: _kPickerSheetHeight,
padding: const EdgeInsets.only(top: 8.0),
padding: const EdgeInsets.only(top: 6.0),
color: CupertinoColors.white,
child: DefaultTextStyle(
style: const TextStyle(
......@@ -95,6 +85,47 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
);
}
Widget _buildColorPicker(BuildContext context) {
final FixedExtentScrollController scrollController =
FixedExtentScrollController(initialItem: _selectedColorIndex);
return GestureDetector(
onTap: () async {
await showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoPicker(
scrollController: scrollController,
itemExtent: _kPickerItemHeight,
backgroundColor: CupertinoColors.white,
onSelectedItemChanged: (int index) {
setState(() => _selectedColorIndex = index);
},
children: List<Widget>.generate(coolColorNames.length, (int index) {
return Center(child:
Text(coolColorNames[index]),
);
}),
),
);
},
);
},
child: _buildMenu(
<Widget>[
const Text('Favorite Color'),
Text(
coolColorNames[_selectedColorIndex],
style: const TextStyle(
color: CupertinoColors.inactiveGray
),
),
],
),
);
}
Widget _buildCountdownTimerPicker(BuildContext context) {
return GestureDetector(
onTap: () {
......@@ -105,9 +136,7 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
CupertinoTimerPicker(
initialTimerDuration: timer,
onTimerDurationChanged: (Duration newTimer) {
setState(() {
timer = newTimer;
});
setState(() => timer = newTimer);
},
),
);
......@@ -115,15 +144,105 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
);
},
child: _buildMenu(
<Widget>[
const Text('Countdown Timer'),
Text(
'${timer.inHours}:'
<Widget>[
const Text('Countdown Timer'),
Text(
'${timer.inHours}:'
'${(timer.inMinutes % 60).toString().padLeft(2,'0')}:'
'${(timer.inSeconds % 60).toString().padLeft(2,'0')}',
style: const TextStyle(color: CupertinoColors.inactiveGray),
),
]
style: const TextStyle(color: CupertinoColors.inactiveGray),
),
],
),
);
}
Widget _buildDatePicker(BuildContext context) {
return GestureDetector(
onTap: () {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: date,
onDateTimeChanged: (DateTime newDateTime) {
setState(() => date = newDateTime);
},
),
);
},
);
},
child: _buildMenu(
<Widget>[
const Text('Date'),
Text(
DateFormat.yMMMMd().format(date),
style: const TextStyle(color: CupertinoColors.inactiveGray),
),
]
),
);
}
Widget _buildTimePicker(BuildContext context) {
return GestureDetector(
onTap: () {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
initialDateTime: time,
onDateTimeChanged: (DateTime newDateTime) {
setState(() => time = newDateTime);
},
),
);
},
);
},
child: _buildMenu(
<Widget>[
const Text('Time'),
Text(
DateFormat.jm().format(time),
style: const TextStyle(color: CupertinoColors.inactiveGray),
),
],
),
);
}
Widget _buildDateAndTimePicker(BuildContext context) {
return GestureDetector(
onTap: () {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoDatePicker(
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: dateTime,
onDateTimeChanged: (DateTime newDateTime) {
setState(() => dateTime = newDateTime);
},
),
);
},
);
},
child: _buildMenu(
<Widget>[
const Text('Date and Time'),
Text(
DateFormat.yMMMd().add_jm().format(dateTime),
style: const TextStyle(color: CupertinoColors.inactiveGray),
),
],
),
);
}
......@@ -146,28 +265,11 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
child: ListView(
children: <Widget>[
const Padding(padding: EdgeInsets.only(top: 32.0)),
GestureDetector(
onTap: () async {
await showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(_buildColorPicker());
},
);
},
child: _buildMenu(
<Widget>[
const Text('Favorite Color'),
Text(
coolColorNames[_selectedColorIndex],
style: const TextStyle(
color: CupertinoColors.inactiveGray
),
),
]
),
),
_buildColorPicker(context),
_buildCountdownTimerPicker(context),
_buildDatePicker(context),
_buildTimePicker(context),
_buildDateAndTimePicker(context),
],
),
),
......
......@@ -7,6 +7,46 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
/// Determines the order of the columns inside [CupertinoDatePicker] in
/// time and date time mode.
enum DatePickerDateTimeOrder {
/// Order of the columns, from left to right: date, hour, minute, am/pm.
///
/// Example: [Fri Aug 31 | 02 | 08 | PM].
date_time_dayPeriod,
/// Order of the columns, from left to right: date, am/pm, hour, minute.
///
/// Example: [Fri Aug 31 | PM | 02 | 08].
date_dayPeriod_time,
/// Order of the columns, from left to right: hour, minute, am/pm, date.
///
/// Example: [02 | 08 | PM | Fri Aug 31].
time_dayPeriod_date,
/// Order of the columns, from left to right: am/pm, hour, minute, date.
///
/// Example: [PM | 02 | 08 | Fri Aug 31].
dayPeriod_time_date,
}
/// Determines the order of the columns inside [CupertinoDatePicker] in date mode.
enum DatePickerDateOrder {
/// Order of the columns, from left to right: day, month, year.
///
/// Example: [12 | March | 1996]
dmy,
/// Order of the columns, from left to right: month, day, year.
///
/// Example: [March | 12 | 1996]
mdy,
/// Order of the columns, from left to right: year, month, day.
///
/// Example: [1996 | March | 12]
ymd,
/// Order of the columns, from left to right: year, day, month.
///
/// Example: [1996 | 12 | March]
ydm,
}
/// Defines the localized resource values used by the Cupertino widgets.
///
......@@ -61,6 +101,9 @@ abstract class CupertinoLocalizations {
/// - Arabic: ٠١
String datePickerHour(int hour);
/// Semantics label for the given hour value in [CupertinoDatePicker].
String datePickerHourSemanticsLabel(int hour);
/// Minute that is shown in [CupertinoDatePicker] spinner corresponding
/// to the given minute value.
///
......@@ -70,9 +113,14 @@ abstract class CupertinoLocalizations {
/// - Arabic: ٠١
String datePickerMinute(int minute);
/// Semantics label for the given minute value in [CupertinoDatePicker].
String datePickerMinuteSemanticsLabel(int minute);
/// The order of the date elements that will be shown in [CupertinoDatePicker].
/// Can be any permutation of 'DMY' ('D': day, 'M': month, 'Y': year).
String get datePickerDateOrder;
DatePickerDateOrder get datePickerDateOrder;
/// The order of the time elements that will be shown in [CupertinoDatePicker].
DatePickerDateTimeOrder get datePickerDateTimeOrder;
/// The abbreviation for ante meridiem (before noon) shown in the time picker.
String get anteMeridiemAbbreviation;
......@@ -216,9 +264,19 @@ class DefaultCupertinoLocalizations implements CupertinoLocalizations {
@override
String datePickerHour(int hour) => hour.toString().padLeft(2, '0');
@override
String datePickerHourSemanticsLabel(int hour) => hour.toString() + " o'clock";
@override
String datePickerMinute(int minute) => minute.toString().padLeft(2, '0');
@override
String datePickerMinuteSemanticsLabel(int minute) {
if (minute == 1)
return '1 minute';
return minute.toString() + ' minutes';
}
@override
String datePickerMediumDate(DateTime date) {
return '${_shortWeekdays[date.weekday - DateTime.monday]} '
......@@ -227,7 +285,10 @@ class DefaultCupertinoLocalizations implements CupertinoLocalizations {
}
@override
String get datePickerDateOrder => 'MDY';
DatePickerDateOrder get datePickerDateOrder => DatePickerDateOrder.mdy;
@override
DatePickerDateTimeOrder get datePickerDateTimeOrder => DatePickerDateTimeOrder.date_time_dayPeriod;
@override
String get anteMeridiemAbbreviation => 'AM';
......
......@@ -13,9 +13,12 @@ void main() {
expect(localizations.datePickerMonth(1), isNotNull);
expect(localizations.datePickerDayOfMonth(1), isNotNull);
expect(localizations.datePickerHour(0), isNotNull);
expect(localizations.datePickerHourSemanticsLabel(0), isNotNull);
expect(localizations.datePickerMinute(0), isNotNull);
expect(localizations.datePickerMinuteSemanticsLabel(0), isNotNull);
expect(localizations.datePickerMediumDate(DateTime.now()), isNotNull);
expect(localizations.datePickerDateOrder, isNotNull);
expect(localizations.datePickerDateTimeOrder, isNotNull);
expect(localizations.anteMeridiemAbbreviation, isNotNull);
expect(localizations.postMeridiemAbbreviation, isNotNull);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment