material_drum_picker 1.2.0
material_drum_picker: ^1.2.0 copied to clipboard
A Material 3 date picker with an iOS-style drum roller, full API parity with showDatePicker and CupertinoDatePicker, and drum, calendar and input modes.
material_drum_picker #
A Material Design 3 date, time, and date+time picker with an iOS style drum
roller. It offers full API parity with Flutter's showDatePicker and
CupertinoDatePicker, uses Material 3 color tokens, and ships three context
aware date modes (drum, calendar, and keyboard input).
Showcase #
Every look below is rendered straight from the package: the drum mode (with day of week), the calendar mode (quick selects plus disabled weekends), the keyboard input mode, a combined date and time picker, and a dark theme.
[material_drum_picker showcase]
Run the live demo for every option with cd example && flutter run, then open
the Showcase screen.
Features #
- Drum mode. An iOS style scroll wheel. Ideal for birth dates and expiry dates.
- Calendar mode. A Material 3 calendar grid with year navigation and configurable quick select chips.
- Input mode. A keyboard text field with live
MM/DD/YYYYvalidation. - Date and time. Opt in with
pickTime: true(orshowDrumDateTimePicker) to add an hour and minute drum, plus an AM/PM column in 12 hour mode. - Time only. Use
DrumTimePickerorshowDrumTimePickerto pick just aTimeOfDay, configurable for AM/PM or 24 hour mode. - Full API parity with
showDatePickerandCupertinoDatePicker. Shared parameters keep the same names so migration is a one line change. selectableDayPredicateto disable weekends, holidays, or any custom rule, enforced in all three date modes.quickSelectOptionsfor custom chips such as Today, Next Monday, or +3 Days.columnOrderfor Day/Month/Year, Month/Day/Year, or Year/Month/Day.- Material 3 theming through
ColorSchemetokens, with per app overrides via theDrumPickerThemeextension. - Right to left support for Arabic, Hebrew, and Persian, with the weekday and column order flipping automatically.
- Accessibility: 44dp touch targets, keyboard navigation in the calendar, screen reader semantics, and reduced motion support.
- All six platforms: Android, iOS, web, macOS, Windows, and Linux.
- Zero runtime dependencies beyond Flutter and
intl.
Pickers at a glance #
| Function | Returns | Use it for |
|---|---|---|
showDrumDatePicker |
DateTime? |
A date |
showDrumDateTimePicker |
DateTime? |
A date and a time |
showDrumTimePicker |
TimeOfDay? |
A time only |
Each function has an inline widget equivalent (DrumPicker and
DrumTimePicker) for embedding in a form without a dialog.
Date and time #
[date and time picker]
Time only #
[time picker]
Installation #
dependencies:
material_drum_picker: ^1.2.0
Add flutter_localizations to your app if you have not already:
dependencies:
flutter_localizations:
sdk: flutter
Then register the delegates in your MaterialApp:
MaterialApp(
localizationsDelegates: GlobalMaterialLocalizations.delegates,
supportedLocales: const [Locale('en'), /* your locales */],
)
Quick start #
A date (drop in replacement for showDatePicker) #
import 'package:material_drum_picker/material_drum_picker.dart';
final DateTime? picked = await showDrumDatePicker(
context: context,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
A time only #
final TimeOfDay? time = await showDrumTimePicker(
context: context,
initialTime: TimeOfDay.now(),
use24hFormat: true, // null follows MediaQuery.alwaysUse24HourFormat
minuteInterval: 5, // 0, 5, 10, ...
);
Inline, embedded in a form:
DrumTimePicker(
initialTime: const TimeOfDay(hour: 9, minute: 0),
use24hFormat: false, // shows an AM/PM column
minuteInterval: 15,
showActions: false,
onChanged: (time) => setState(() => _time = time),
)
A date and time #
final DateTime? when = await showDrumDateTimePicker(
context: context,
firstDate: DateTime(2020),
lastDate: DateTime(2030),
use24hFormat: true,
minuteInterval: 15,
);
// `when` carries the chosen hour and minute.
Birth date picker #
final today = DateTime.now();
final birthDate = await showDrumDatePicker(
context: context,
initialMode: DrumPickerMode.drum, // a wheel for distant dates
firstDate: DateTime(today.year - 120),
lastDate: DateTime(today.year - 18, today.month, today.day),
columnOrder: DrumColumnOrder.dmy, // Day, Month, Year
showModeToggle: false, // lock to drum mode
helpText: 'SELECT BIRTH DATE',
);
Appointment picker without weekends #
final appointment = await showDrumDatePicker(
context: context,
initialMode: DrumPickerMode.calendar,
firstDate: DateTime.now(),
lastDate: DateTime.now().add(const Duration(days: 90)),
selectableDayPredicate: (day) =>
day.weekday != DateTime.saturday && day.weekday != DateTime.sunday,
confirmText: 'BOOK APPOINTMENT',
);
Custom quick selects #
showDrumDatePicker(
context: context,
firstDate: DateTime.now().add(const Duration(days: 1)),
lastDate: DateTime.now().add(const Duration(days: 30)),
quickSelectOptions: [
DrumQuickSelect.relative(label: 'Express +1', offset: const Duration(days: 1)),
DrumQuickSelect.relative(label: 'Standard +3', offset: const Duration(days: 3)),
DrumQuickSelect.relative(label: 'Economy +7', offset: const Duration(days: 7)),
],
);
API reference #
showDrumDatePicker and showDrumDateTimePicker #
| Parameter | Type | Default | Description |
|---|---|---|---|
context |
BuildContext |
required | Build context |
firstDate |
DateTime |
required | Minimum selectable date |
lastDate |
DateTime |
required | Maximum selectable date |
initialDate |
DateTime? |
today | Pre selected date |
currentDate |
DateTime? |
DateTime.now() |
The "today" marker |
selectableDayPredicate |
SelectableDayPredicate? |
null | Return false to disable a day |
initialMode |
DrumPickerMode |
.drum |
Starting date mode |
showModeToggle |
bool |
true |
Show the mode tabs |
columnOrder |
DrumColumnOrder? |
locale default | Column order in drum mode |
showDayOfWeekInDrum |
bool |
false |
Show weekday in the drum day column |
showQuickSelects |
bool |
true |
Show quick select chips |
quickSelectOptions |
List<DrumQuickSelect>? |
Today/Tomorrow/+7d | Custom chips |
pickTime |
bool |
false |
Also pick a time of day |
use24hFormat |
bool? |
ambient | 24 hour time strip (no AM/PM) |
minuteInterval |
int |
1 |
Minute granularity (a divisor of 60) |
helpText |
String? |
'SELECT DATE' |
Header label |
confirmText |
String? |
'OK' |
Confirm button text |
cancelText |
String? |
'Cancel' |
Cancel button text |
errorFormatText |
String? |
'Invalid format' |
Input mode format error |
errorInvalidText |
String? |
'Out of range' |
Input mode range error |
fieldHintText |
String? |
'MM/DD/YYYY' |
Input field hint |
fieldLabelText |
String? |
'Enter Date' |
Input field label |
locale |
Locale? |
ambient | Locale override |
textDirection |
TextDirection? |
ambient | Text direction override |
barrierDismissible |
bool |
true |
Tap outside to dismiss |
barrierColor |
Color? |
Colors.black54 |
Barrier color |
barrierLabel |
String? |
localized | Barrier accessibility label |
useRootNavigator |
bool |
true |
Use the root navigator |
routeSettings |
RouteSettings? |
null | Route settings |
restorationId |
String? |
null | State restoration id |
anchorPoint |
Offset? |
null | Split screen anchor |
builder |
TransitionBuilder? |
null | Wrap the dialog with a Theme, and so on |
showDrumDateTimePicker takes the same parameters and is simply
showDrumDatePicker with pickTime set to true.
showDrumTimePicker #
| Parameter | Type | Default | Description |
|---|---|---|---|
context |
BuildContext |
required | Build context |
initialTime |
TimeOfDay? |
now | Pre selected time |
use24hFormat |
bool? |
ambient | 24 hour mode (no AM/PM column) |
minuteInterval |
int |
1 |
Minute granularity (a divisor of 60) |
helpText |
String? |
'SELECT TIME' |
Header label |
confirmText |
String? |
'OK' |
Confirm button text |
cancelText |
String? |
'Cancel' |
Cancel button text |
locale |
Locale? |
ambient | Locale override |
textDirection |
TextDirection? |
ambient | Text direction override |
barrierDismissible |
bool |
true |
Tap outside to dismiss |
barrierColor |
Color? |
Colors.black54 |
Barrier color |
barrierLabel |
String? |
null | Barrier accessibility label |
useRootNavigator |
bool |
true |
Use the root navigator |
routeSettings |
RouteSettings? |
null | Route settings |
anchorPoint |
Offset? |
null | Split screen anchor |
builder |
TransitionBuilder? |
null | Wrap the dialog with a Theme, and so on |
Inline widgets #
DrumPicker accepts every showDrumDatePicker parameter, plus the callbacks
onChanged, onConfirmed, onCancelled, and onModeChanged, and the
showActions flag. DrumTimePicker accepts every showDrumTimePicker
parameter, plus onChanged, onConfirmed, onCancelled, and showActions.
Set showActions: false to drop the built in Cancel and OK buttons and drive
the value yourself with onChanged.
DrumColumnOrder #
| Value | Format | Typical regions |
|---|---|---|
dmy |
15 Jun 2024 | UK, Europe, MENA, Australia |
mdy |
Jun 15 2024 | United States, Canada |
ymd |
2024 Jun 15 | Japan, China, Korea |
ydm |
2024 15 Jun | Rarely used |
DrumPickerMode #
| Value | Best for |
|---|---|
drum |
Birth dates, expiry dates, distant past or future |
calendar |
Scheduling events, appointments, near future |
input |
Power users, accessibility tools, typed entry |
DrumPickerTheme #
Add it to ThemeData.extensions to override individual tokens:
ThemeData(
useMaterial3: true,
extensions: const [
DrumPickerTheme(
headerBackgroundColor: Color(0xFF004D40),
headerTextColor: Colors.white,
itemExtent: 48,
visibleItemCount: 3,
),
],
)
Localization #
The pickers follow the ambient locale for month and weekday names, the first
day of the week, AM/PM labels, the column order, and right to left layout. Pass
locale and textDirection to override them for a single picker. The time
format follows MediaQuery.alwaysUse24HourFormat unless you set use24hFormat.
Migration from showDatePicker #
Most parameters keep the same name, so usually only the function name changes:
// Before
showDatePicker(
context: context,
initialDate: myDate,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
selectableDayPredicate: myPredicate,
helpText: 'PICK DATE',
locale: myLocale,
);
// After, identical parameter names
showDrumDatePicker(
context: context,
initialDate: myDate,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
selectableDayPredicate: myPredicate,
helpText: 'PICK DATE',
locale: myLocale,
initialMode: DrumPickerMode.calendar, // optional, same feel as showDatePicker
);
Contributing #
Contributions are welcome. Please read CONTRIBUTING.md for the development setup and the checks that run in CI, and note the Code of Conduct. To report a security issue, see SECURITY.md.
Roadmap #
- v1.0 Single date picker (drum, calendar, and input modes).
- v1.1 Combined date and time picking (
pickTime,showDrumDateTimePicker). - v1.2 Standalone time picker (
DrumTimePicker,showDrumTimePicker). - Next Date range selection (
showDrumDateRangePicker).
License #
MIT, 2026. See LICENSE.