showDatePicker、showTimePicker 是 flutter 提供的日期选择器弹框。
1. showDatePicker
Future<DateTime?> showDatePicker({
required BuildContext context,
required DateTime initialDate,
required DateTime firstDate,
required DateTime lastDate,
DateTime? currentDate,
DatePickerEntryMode initialEntryMode = DatePickerEntryMode.calendar,
SelectableDayPredicate? selectableDayPredicate,
String? helpText,
String? cancelText,
String? confirmText,
Locale? locale,
bool useRootNavigator = true,
RouteSettings? routeSettings,
TextDirection? textDirection,
TransitionBuilder? builder,
DatePickerMode initialDatePickerMode = DatePickerMode.day,
String? errorFormatText,
String? errorInvalidText,
String? fieldHintText,
String? fieldLabelText,
})
showDatePicker 属性
showDatePicker属性 | 介绍 |
---|---|
context | @required BuildContext,上下文 context |
initialDate | @required DateTime,日历初始化日期 |
firstDate | @required DateTime,日历开始日期 |
lastDate | @required DateTime,日历结束日期 |
currentDate | DateTime 当前日期 |
initialEntryMode | DatePickerEntryMode 日历弹框样式 calendar : 默认显示日历,可切换成输入模式,input :默认显示输入模式,可切换到日历,calendarOnly :只显示日历,inputOnly :只显示输入模式 |
selectableDayPredicate | (DateTime dayTime){ return true;} 一个返回 bool 值的函数,自定义哪些日期可选 |
helpText | 左上角文字 |
cancelText | 取消按钮文字 |
confirmText | 确认按钮文字 |
locale | 地区设置,以后多语言部分在详解 |
useRootNavigator | 是否使用根导航,默认为 true,官方文档也没做详解,暂时没用到 |
routeSettings | 路由设置,官方文档也没做详解,暂时没用到 |
textDirection | 水平方向 显示方向 默认 ltr |
builder | 创建器,和直接创建基本一致,可以定制主题 |
initialDatePickerMode | DatePickerMode.day 与 DatePickerMode.year 两种, DatePickerMode.day 默认显示某一天的选择界面,可切换到年份选择界面, DatePickerMode.year 默认显示年份,可切换到某一天的选择界面 |
errorFormatText | 格式错误是下方提示 |
fieldHintText | 输入框默认提示语 |
fieldLabelText | 输入框上方提示语 |
errorInvalidText | 输入了不在 first 与 last 之间的日期提示语 |
示例1-日期选择弹窗
Future<DateTime?> _showDatePickerForDay(BuildContext context) {
return showDatePicker(
context: context, // 上下文
initialDate: DateTime(2022, 5, 20), // 初始化选中日期
firstDate: DateTime(2022, 5), // 开始日期
lastDate: DateTime(2022, 7), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode
.calendar, // 日历弹框样式 calendar: 默认显示日历,可切换成输入模式,input:默认显示输入模式,可切换到日历,calendarOnly:只显示日历,inputOnly:只显示输入模式
selectableDayPredicate: (dayTime) {
// 自定义哪些日期可选
if (dayTime == DateTime(2022, 5, 6) ||
dayTime == DateTime(2022, 6, 8)) {
return false;
}
return true;
},
helpText: "请选择日期", // 左上角提示文字
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
initialDatePickerMode: DatePickerMode.day, // 日期选择模式 默认为天
useRootNavigator: true, // 是否使用根导航器
errorFormatText: "输入日期格式有误,请重新输入", // 输入日期 格式错误提示
errorInvalidText: "输入日期不合法,请重新输入", // 输入日期 不在first 与 last 之间提示
fieldLabelText: "输入所选日期", // 输入框上方 提示
fieldHintText: "请输入日期", // 输入框为空时提示
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
120.gif
示例2 - 年份选择弹窗
Future<DateTime?> _showDatePickerForYear(BuildContext context) {
return showDatePicker(
context: context,
initialDate: DateTime(1991), // 初始化选中日期
firstDate: DateTime(1990), // 开始日期
lastDate: DateTime(2025), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode.input, // 日历弹框模式
selectableDayPredicate: (daytime) {
// 自定义哪些日期可选
if (daytime == DateTime(2000)) {
return false;
}
return true;
},
initialDatePickerMode: DatePickerMode.year, // 日期选择模式 默认为天
helpText: "请选择年份", // 左上角提示
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
useRootNavigator: true, // 是否使用根导航器
errorFormatText: "输入格式有误", // 输入日期 格式错误提示
errorInvalidText: "输入年份不合法", // 输入日期 不在first 与 last 之间提示
fieldHintText: "请输入年份", // 输入框为空时提示
fieldLabelText: "输入正确的年份", // 输入框上方 提示
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
121.gif
示例3 - 仅显示日历选择
Future<DateTime?> _showDatePickerForCalendarOnly(BuildContext context) {
return showDatePicker(
context: context, // 上下文
initialDate: DateTime(2022, 5, 20), // 初始化选中日期
firstDate: DateTime(2022, 5), // 开始日期
lastDate: DateTime(2022, 7), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode
.calendarOnly, // 日历弹框样式 calendar: 默认显示日历,可切换成输入模式,input:默认显示输入模式,可切换到日历,calendarOnly:只显示日历,inputOnly:只显示输入模式
selectableDayPredicate: (dayTime) {
// 自定义哪些日期可选
if (dayTime == DateTime(2022, 5, 6) || dayTime == DateTime(2022, 6, 8)) {
return false;
}
return true;
},
helpText: "请选择日期", // 左上角提示文字
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
initialDatePickerMode: DatePickerMode.day, // 日期选择模式 默认为天
useRootNavigator: true, // 是否使用根导航器
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
image.png
示例4 - 仅显示日历输入
Future<DateTime?> _showDatePickerForInputOnly(BuildContext context) {
return showDatePicker(
context: context,
initialDate: DateTime(1991), // 初始化选中日期
firstDate: DateTime(1990), // 开始日期
lastDate: DateTime(2025), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode.inputOnly, // 日历弹框模式
selectableDayPredicate: (daytime) {
// 自定义哪些日期可选
if (daytime == DateTime(2000)) {
return false;
}
return true;
},
initialDatePickerMode: DatePickerMode.year, // 日期选择模式 默认为天
helpText: "请选择年份", // 左上角提示
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
useRootNavigator: true, // 是否使用根导航器
errorFormatText: "输入格式有误", // 输入日期 格式错误提示
errorInvalidText: "输入年份不合法", // 输入日期 不在first 与 last 之间提示
fieldHintText: "请输入年份", // 输入框为空时提示
fieldLabelText: "输入正确的年份", // 输入框上方 提示
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
image.png
示例5 - 日期选择器主题设置
Future<DateTime?> _showDatePickerForTheme(BuildContext context) {
return showDatePicker(
context: context, // 上下文
initialDate: DateTime(2022, 5, 20), // 初始化选中日期
firstDate: DateTime(2022, 5), // 开始日期
lastDate: DateTime(2022, 7), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode
.calendarOnly, // 日历弹框样式 calendar: 默认显示日历,可切换成输入模式,input:默认显示输入模式,可切换到日历,calendarOnly:只显示日历,inputOnly:只显示输入模式
selectableDayPredicate: (dayTime) {
// 自定义哪些日期可选
if (dayTime == DateTime(2022, 5, 6) || dayTime == DateTime(2022, 6, 8)) {
return false;
}
return true;
},
builder: (context, child) {
return Theme(
data: ThemeData(
primarySwatch: Colors.amber,
),
child: child!,
);
},
helpText: "请选择日期", // 左上角提示文字
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
initialDatePickerMode: DatePickerMode.day, // 日期选择模式 默认为天
useRootNavigator: true, // 是否使用根导航器
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
image.png
2. showTimePicker
Future<TimeOfDay?> showTimePicker({
required BuildContext context,
required TimeOfDay initialTime,
TransitionBuilder? builder,
bool useRootNavigator = true,
TimePickerEntryMode initialEntryMode = TimePickerEntryMode.dial,
String? cancelText,
String? confirmText,
String? helpText,
String? errorInvalidText,
String? hourLabelText,
String? minuteLabelText,
RouteSettings? routeSettings,
EntryModeChangeCallback? onEntryModeChanged,
})
showTimePicker属性
showTimePicker属性 | 介绍 |
---|---|
context | 上下文 |
initialTime | 初始化时间 初始化选中时间 |
builder | 构造器 |
useRootNavigator | 是否使用根导航,默认为 true |
initialEntryMode | 时间选择模式 TimePickerEntryMode , dial input ,默认dial
|
cancelText | 取消按钮 文案 |
confirmText | 确认按钮 文案 |
helpText | 左上角提示语 |
errorInvalidText | 输入时间不合法提示语 |
hourLabelText | 小时 提示语 |
minuteLabelText | 分钟 提示语 |
RouteSettings | 路由配置 |
onEntryModeChanged | 时间选择模式变化回调 |
示例
Future<TimeOfDay?> _showTimePicker(BuildContext context) {
return showTimePicker(
context: context, // 上下文
initialTime: TimeOfDay.now(), // 初始化时间
initialEntryMode: TimePickerEntryMode.input, // 时间选择模式 dial input
useRootNavigator: true, // 是否使用根导航 默认true
cancelText: "取消", // 取消按钮 文案
confirmText: "确认", // 确认按钮 文案
helpText: "请选择时间", // 左上角提示语
errorInvalidText: "输入时间不合法", // 属于时间不合法 提示语
hourLabelText: "小时", // 小时 提示语
minuteLabelText: "分钟", // 分钟 提示语
// 时间选择模式变化 回调
onEntryModeChanged: (mode) {
print("Mode Changed $mode");
},
);
}
122.gif
3. showDatePicker 原理
showDatePicker 也是弹出对话框,内部实际上是调用showDialog。showDialog的builder用于创建DatePickerDialog。
showDatePicker 核心代码
...
Widget dialog = DatePickerDialog(
initialDate: initialDate,
firstDate: firstDate,
lastDate: lastDate,
currentDate: currentDate,
initialEntryMode: initialEntryMode,
selectableDayPredicate: selectableDayPredicate,
helpText: helpText,
cancelText: cancelText,
confirmText: confirmText,
initialCalendarMode: initialDatePickerMode,
errorFormatText: errorFormatText,
errorInvalidText: errorInvalidText,
fieldHintText: fieldHintText,
fieldLabelText: fieldLabelText,
);
...
return showDialog<DateTime>(
context: context,
useRootNavigator: useRootNavigator,
routeSettings: routeSettings,
builder: (BuildContext context) {
return builder == null ? dialog : builder(context, dialog);
},
);
...
DatePickerDialog 核心代码
final header = SizedBox(
...
...
);
final picker = CalendarDatePicker(
...
...
);
final Widget actions = Container(
...
...
);
return Dialog(
...
child: AnimatedContainer(
...
child: MediaQuery(
...
child: Builder(builder: (BuildContext context) {
switch (orientation) {
case Orientation.portrait:
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
Expanded(child: picker),
actions,
],
);
case Orientation.landscape:
return Row(
...
);
}
}),
),
),
);
showTimePicker 和 showDatePicker 类似,也是调用showDialog,只不过showTimePicker build的是TimePickerDialog。
自定义DatePicker MSCustomDatePicker
class MSCustomDatePicker extends StatelessWidget {
MSCustomDatePicker({
Key? key,
required this.initialDate,
required this.firstDate,
required this.lastDate,
this.helpText,
this.cancelText = "取消",
this.sureText = "确定",
});
final DateTime initialDate;
final DateTime firstDate;
final DateTime lastDate;
final String? helpText;
final String cancelText;
final String sureText;
DateTime? _chooseDateTime;
@override
Widget build(BuildContext context) {
_chooseDateTime = initialDate;
final ValueNotifier<DateTime> _chooseDateValueNoti =
ValueNotifier<DateTime>(initialDate);
final double textScaleFactor =
math.min(MediaQuery.of(context).textScaleFactor, 1.3);
final Size _calendarPortraitDialogSize = Size(330.0, 518.0);
final Size dialogSize = _calendarPortraitDialogSize * textScaleFactor;
final MaterialLocalizations localizations =
MaterialLocalizations.of(context);
final header = SizedBox(
height: 120,
child: Material(
color: Theme.of(context).primaryColor,
child: Padding(
padding: EdgeInsetsDirectional.only(start: 24, end: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 16),
Text(
helpText ?? "",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey[200]),
),
const Flexible(child: SizedBox(height: 38)),
ValueListenableBuilder<DateTime>(
valueListenable: _chooseDateValueNoti,
builder: (context, datetime, child) {
final String dateText =
localizations.formatMediumDate(datetime);
return Text(
dateText,
textScaleFactor: 2.0,
style: TextStyle(color: Colors.white),
);
},
),
],
),
),
),
);
final picker = CalendarDatePicker(
initialDate: initialDate,
firstDate: firstDate,
lastDate: lastDate,
currentDate: DateTime.now(),
onDateChanged: (datetime) {
_chooseDateTime = datetime;
_chooseDateValueNoti.value = datetime;
print("DateChanged $datetime");
},
);
final Widget actions = Container(
alignment: AlignmentDirectional.centerEnd,
constraints: const BoxConstraints(minHeight: 52.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: OverflowBar(
spacing: 8,
children: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(cancelText),
),
TextButton(
onPressed: () {
Navigator.of(context).pop(_chooseDateTime);
},
child: Text(sureText),
),
],
),
);
return Dialog(
insetPadding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
child: AnimatedContainer(
duration: Duration(milliseconds: 150),
height: dialogSize.height,
width: dialogSize.width,
curve: Curves.easeIn,
child: Builder(
builder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
header,
Expanded(child: picker),
actions,
],
);
},
),
),
);
}
}
使用自定义的DatePicker
class MSCustomDatePickerDemo extends StatelessWidget {
const MSCustomDatePickerDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("MSCustomDatePickerDemo")),
body: Padding(
padding: EdgeInsets.all(24),
child: ElevatedButton(
child: Text("CustomDatePicker"),
onPressed: () async {
DateTime? _dateTime = await _showCustomDatePicker(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
),
),
);
}
Future<DateTime?> _showCustomDatePicker(BuildContext context) {
return showDialog<DateTime>(
context: context,
builder: (context) {
return MSCustomDatePicker(
initialDate: DateTime.now(),
firstDate: DateTime(2021, 10, 10),
lastDate: DateTime(2022, 10, 10),
helpText: "请选择日期",
);
},
);
}
}
124.gif
4. Demo
MSDateAndTimePickerDemo
class MSDateAndTimePickerDemo extends StatelessWidget {
const MSDateAndTimePickerDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("DateAndTimePickerDemo")),
body: Padding(
padding: EdgeInsets.all(16),
child: SingleChildScrollView(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
DateTime? _dateTime = await _showDatePickerForDay(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
child: Text("DatePicker-Day"),
),
ElevatedButton(
onPressed: () async {
DateTime? _dateTime = await _showDatePickerForYear(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
child: Text("DatePicker-Year"),
),
ElevatedButton(
onPressed: () async {
DateTime? _dateTime =
await _showDatePickerForCalendarOnly(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
child: Text("DatePicker-Day-CalendarOnly"),
),
ElevatedButton(
onPressed: () async {
DateTime? _dateTime =
await _showDatePickerForInputOnly(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
child: Text("DatePicker-Year-InputOnly"),
),
ElevatedButton(
onPressed: () async {
DateTime? _dateTime =
await _showDatePickerForTheme(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
child: Text("DatePicker-Day-Theme"),
),
ElevatedButton(
onPressed: () async {
TimeOfDay? _dateTime = await _showTimePicker(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
child: Text("DatePicker-Time"),
),
],
),
),
),
),
);
}
Future<DateTime?> _showDatePickerForDay(BuildContext context) {
return showDatePicker(
context: context, // 上下文
initialDate: DateTime(2022, 5, 20), // 初始化选中日期
firstDate: DateTime(2022, 5), // 开始日期
lastDate: DateTime(2022, 7), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode
.calendar, // 日历弹框样式 calendar: 默认显示日历,可切换成输入模式,input:默认显示输入模式,可切换到日历,calendarOnly:只显示日历,inputOnly:只显示输入模式
selectableDayPredicate: (dayTime) {
// 自定义哪些日期可选
if (dayTime == DateTime(2022, 5, 6) ||
dayTime == DateTime(2022, 6, 8)) {
return false;
}
return true;
},
helpText: "请选择日期", // 左上角提示文字
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
initialDatePickerMode: DatePickerMode.day, // 日期选择模式 默认为天
useRootNavigator: true, // 是否使用根导航器
errorFormatText: "输入日期格式有误,请重新输入", // 输入日期 格式错误提示
errorInvalidText: "输入日期不合法,请重新输入", // 输入日期 不在first 与 last 之间提示
fieldLabelText: "输入所选日期", // 输入框上方 提示
fieldHintText: "请输入日期", // 输入框为空时提示
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
Future<DateTime?> _showDatePickerForYear(BuildContext context) {
return showDatePicker(
context: context,
initialDate: DateTime(1991), // 初始化选中日期
firstDate: DateTime(1990), // 开始日期
lastDate: DateTime(2025), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode.input, // 日历弹框模式
selectableDayPredicate: (daytime) {
// 自定义哪些日期可选
if (daytime == DateTime(2000)) {
return false;
}
return true;
},
initialDatePickerMode: DatePickerMode.year, // 日期选择模式 默认为天
helpText: "请选择年份", // 左上角提示
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
useRootNavigator: true, // 是否使用根导航器
errorFormatText: "输入格式有误", // 输入日期 格式错误提示
errorInvalidText: "输入年份不合法", // 输入日期 不在first 与 last 之间提示
fieldHintText: "请输入年份", // 输入框为空时提示
fieldLabelText: "输入正确的年份", // 输入框上方 提示
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
Future<DateTime?> _showDatePickerForCalendarOnly(BuildContext context) {
return showDatePicker(
context: context, // 上下文
initialDate: DateTime(2022, 5, 20), // 初始化选中日期
firstDate: DateTime(2022, 5), // 开始日期
lastDate: DateTime(2022, 7), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode
.calendarOnly, // 日历弹框样式 calendar: 默认显示日历,可切换成输入模式,input:默认显示输入模式,可切换到日历,calendarOnly:只显示日历,inputOnly:只显示输入模式
selectableDayPredicate: (dayTime) {
// 自定义哪些日期可选
if (dayTime == DateTime(2022, 5, 6) ||
dayTime == DateTime(2022, 6, 8)) {
return false;
}
return true;
},
helpText: "请选择日期", // 左上角提示文字
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
initialDatePickerMode: DatePickerMode.day, // 日期选择模式 默认为天
useRootNavigator: true, // 是否使用根导航器
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
Future<DateTime?> _showDatePickerForInputOnly(BuildContext context) {
return showDatePicker(
context: context,
initialDate: DateTime(1991), // 初始化选中日期
firstDate: DateTime(1990), // 开始日期
lastDate: DateTime(2025), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode.inputOnly, // 日历弹框模式
selectableDayPredicate: (daytime) {
// 自定义哪些日期可选
if (daytime == DateTime(2000)) {
return false;
}
return true;
},
initialDatePickerMode: DatePickerMode.year, // 日期选择模式 默认为天
helpText: "请选择年份", // 左上角提示
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
useRootNavigator: true, // 是否使用根导航器
errorFormatText: "输入格式有误", // 输入日期 格式错误提示
errorInvalidText: "输入年份不合法", // 输入日期 不在first 与 last 之间提示
fieldHintText: "请输入年份", // 输入框为空时提示
fieldLabelText: "输入正确的年份", // 输入框上方 提示
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
Future<DateTime?> _showDatePickerForTheme(BuildContext context) {
return showDatePicker(
context: context, // 上下文
initialDate: DateTime(2022, 5, 20), // 初始化选中日期
firstDate: DateTime(2022, 5), // 开始日期
lastDate: DateTime(2022, 7), // 结束日期
currentDate: DateTime.now(), // 当前日期
initialEntryMode: DatePickerEntryMode
.calendarOnly, // 日历弹框样式 calendar: 默认显示日历,可切换成输入模式,input:默认显示输入模式,可切换到日历,calendarOnly:只显示日历,inputOnly:只显示输入模式
selectableDayPredicate: (dayTime) {
// 自定义哪些日期可选
if (dayTime == DateTime(2022, 5, 6) ||
dayTime == DateTime(2022, 6, 8)) {
return false;
}
return true;
},
builder: (context, child) {
return Theme(
data: ThemeData(
primarySwatch: Colors.amber,
),
child: child!,
);
},
helpText: "请选择日期", // 左上角提示文字
cancelText: "Cancel", // 取消按钮 文案
confirmText: "OK", // 确认按钮 文案
initialDatePickerMode: DatePickerMode.day, // 日期选择模式 默认为天
useRootNavigator: true, // 是否使用根导航器
textDirection: TextDirection.ltr, // 水平方向 显示方向 默认 ltr
);
}
Future<TimeOfDay?> _showTimePicker(BuildContext context) {
return showTimePicker(
context: context, // 上下文
initialTime: TimeOfDay.now(), // 初始化时间
initialEntryMode: TimePickerEntryMode.input, // 时间选择模式 dial input
useRootNavigator: true, // 是否使用根导航 默认true
cancelText: "取消", // 取消按钮 文案
confirmText: "确认", // 确认按钮 文案
helpText: "请选择时间", // 左上角提示语
errorInvalidText: "输入时间不合法", // 属于时间不合法 提示语
hourLabelText: "小时", // 小时 提示语
minuteLabelText: "分钟", // 分钟 提示语
// 时间选择模式变化 回调
onEntryModeChanged: (mode) {
print("Mode Changed $mode");
},
);
}
}
123.gif
MSCustomDatePickerDemo
class MSCustomDatePickerDemo extends StatelessWidget {
const MSCustomDatePickerDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("MSCustomDatePickerDemo")),
body: Padding(
padding: EdgeInsets.all(24),
child: ElevatedButton(
child: Text("CustomDatePicker"),
onPressed: () async {
DateTime? _dateTime = await _showCustomDatePicker(context);
if (_dateTime == null) {
print("取消选择");
} else {
print("选择 $_dateTime");
}
},
),
),
);
}
Future<DateTime?> _showCustomDatePicker(BuildContext context) {
return showDialog<DateTime>(
context: context,
builder: (context) {
return MSCustomDatePicker(
initialDate: DateTime.now(),
firstDate: DateTime(2021, 10, 10),
lastDate: DateTime(2022, 10, 10),
helpText: "请选择日期",
);
},
);
}
}
class MSCustomDatePicker extends StatelessWidget {
MSCustomDatePicker({
Key? key,
required this.initialDate,
required this.firstDate,
required this.lastDate,
this.helpText,
this.cancelText = "取消",
this.sureText = "确定",
});
final DateTime initialDate;
final DateTime firstDate;
final DateTime lastDate;
final String? helpText;
final String cancelText;
final String sureText;
DateTime? _chooseDateTime;
@override
Widget build(BuildContext context) {
_chooseDateTime = initialDate;
final ValueNotifier<DateTime> _chooseDateValueNoti =
ValueNotifier<DateTime>(initialDate);
final double textScaleFactor =
math.min(MediaQuery.of(context).textScaleFactor, 1.3);
final Size _calendarPortraitDialogSize = Size(330.0, 518.0);
final Size dialogSize = _calendarPortraitDialogSize * textScaleFactor;
final MaterialLocalizations localizations =
MaterialLocalizations.of(context);
final header = SizedBox(
height: 120,
child: Material(
color: Theme.of(context).primaryColor,
child: Padding(
padding: EdgeInsetsDirectional.only(start: 24, end: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 16),
Text(
helpText ?? "",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey[200]),
),
const Flexible(child: SizedBox(height: 38)),
ValueListenableBuilder<DateTime>(
valueListenable: _chooseDateValueNoti,
builder: (context, datetime, child) {
final String dateText =
localizations.formatMediumDate(datetime);
return Text(
dateText,
textScaleFactor: 2.0,
style: TextStyle(color: Colors.white),
);
},
),
],
),
),
),
);
final picker = CalendarDatePicker(
initialDate: initialDate,
firstDate: firstDate,
lastDate: lastDate,
currentDate: DateTime.now(),
onDateChanged: (datetime) {
_chooseDateTime = datetime;
_chooseDateValueNoti.value = datetime;
print("DateChanged $datetime");
},
);
final Widget actions = Container(
alignment: AlignmentDirectional.centerEnd,
constraints: const BoxConstraints(minHeight: 52.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: OverflowBar(
spacing: 8,
children: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(cancelText),
),
TextButton(
onPressed: () {
Navigator.of(context).pop(_chooseDateTime);
},
child: Text(sureText),
),
],
),
);
return Dialog(
insetPadding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
child: AnimatedContainer(
duration: Duration(milliseconds: 150),
height: dialogSize.height,
width: dialogSize.width,
curve: Curves.easeIn,
child: Builder(
builder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
header,
Expanded(child: picker),
actions,
],
);
},
),
),
);
}
}
124.gif
网友评论