赞
踩
在Flutter 应用开发过程中,或多或少的都会涉及到时间选择器相关的内容。Flutter默认提供了DatePicker日期选择器,如果对样式没有特殊的要求,那么可以使用它来进行时间的选择,默认的样式如下所示。
使用示例代码如下:
import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'dart:async'; class DateTimeDemo extends StatefulWidget { @override _DateTimeDemoState createState() => _DateTimeDemoState(); } class _DateTimeDemoState extends State<DateTimeDemo> { DateTime selectedDate = DateTime.now(); TimeOfDay selectedTime = TimeOfDay(hour: 9, minute: 30); Future<void> _selectDate() async { final DateTime date = await showDatePicker( context: context, initialDate: selectedDate, firstDate: DateTime(1900), lastDate: DateTime(2100), ); if (date == null) return; setState(() { selectedDate = date; }); } Future<void> _selectTime() async { final TimeOfDay time = await showTimePicker( context: context, initialTime: selectedTime, ); if (time == null) return; setState(() { selectedTime = time; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('DateTimeDemo'), elevation: 0.0, ), body: Container( padding: EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ InkWell( onTap: _selectDate, child: Row( children: <Widget>[ Text(DateFormat.yMMMMd().format(selectedDate)), Icon(Icons.arrow_drop_down), ], ), ), InkWell( onTap: _selectTime, child: Row( children: <Widget>[ Text(selectedTime.format(context)), Icon(Icons.arrow_drop_down), ], ), ), ], ), ], ), ) ); } }
可以发现,默认的样式并不是很友好。通常在移动应用开发中,App的涉及多是参考iOS的设计来的,所以这时候,多半需要进行自定义组件了。不管,为了快速的进行开发我们可以选择一些第三方的组件库,如flutter_custom_calendar,此库具有如下的功能:
如下是部分效果图:
实际使用时,我们需要根据样式对该库进行二次开发,首先,新建一个date_picker_widget.dart文件,然后添加如下代码:
import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; class DatePickerWidget extends StatefulWidget { final ValueSetter<String> onSetter; DatePickerWidget({@required this.onSetter}); @override _DatePickerWidgetState createState() => _DatePickerWidgetState(); } class _DatePickerWidgetState extends State<DatePickerWidget> { ValueNotifier<String> text; ValueNotifier<String> selectText; CalendarController controller ; @override Widget build(BuildContext context) { return Column( children: <Widget>[ Container( color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ IconButton(icon: Icon(Icons.navigate_before), onPressed: (){ controller.moveToPreviousMonth(); }), ValueListenableBuilder( valueListenable: text, builder: (context, value, child) { return Text(text.value); }), IconButton( icon: Icon(Icons.navigate_next), onPressed: () { controller.moveToNextMonth(); }), ], ), ), CalendarViewWidget( boxDecoration: BoxDecoration( color: Colors.white ), calendarController: controller, weekBarItemWidgetBuilder: () { return CustomStyleWeekBarItem(); }, dayWidgetBuilder: (dateModel) { return CustomStyleDayWidget(dateModel); }, ), ], ); } List<DateTime> getHighlightedDates() { return List<DateTime>.generate(10, (int index) => DateTime.now().add(Duration(days: 10 * (index + 1))), ); } int maxSelectYear() { return DateTime.now().year; } int maxSelectMounth() { return DateTime.now().month; } int maxSelectDay() { return DateTime.now().day; } @override void initState() { super.initState(); controller = CalendarController( maxSelectYear: maxSelectYear(), maxSelectMonth: maxSelectMounth(), maxSelectDay:maxSelectDay(), ); controller.addMonthChangeListener( (year, month) { text.value = "$year年$month月"; }, ); controller.addOnCalendarSelectListener((dateModel){ String month = dateModel.month < 10 ? '0${dateModel.month}': '${dateModel.month}'; String day = dateModel.day < 10 ? '0${dateModel.day}': '${dateModel.day}'; this.widget.onSetter('${dateModel.year}-${month}-${day}'); }); // controller.addOnCalendarSelectListener((dateModel) { // debugPrint(dateModel.toString()+'+++++++++++'); // //刷新选择的时间 // selectText.value = // "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"; // }); // text = new ValueNotifier("${DateTime.now().year}年${DateTime.now().month}月"); // // selectText = new ValueNotifier( // "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"); } } class CustomStyleWeekBarItem extends BaseWeekBar { final List<String> weekList = ["日","一", "二", "三", "四", "五", "六",]; @override Widget getWeekBarItem(int index) { return Container( child: Center( child: Text(weekList[index]), ), ); } } class CustomStyleDayWidget extends BaseCustomDayWidget { CustomStyleDayWidget(DateModel dateModel) : super(dateModel); @override void drawNormal(DateModel dateModel, Canvas canvas, Size size) { if (!dateModel.isCurrentMonth) { return; } bool isWeekend = dateModel.isWeekend; bool isInRange = dateModel.isInRange; //顶部的文字 TextPainter dayTextPainter = new TextPainter() ..text = TextSpan( text: dateModel.day.toString(), style: new TextStyle( color: !isInRange ? Colors.grey : isWeekend ? Colors.blue : Colors.black, fontSize: 16)) ..textDirection = TextDirection.ltr ..textAlign = TextAlign.center; dayTextPainter.layout(minWidth: size.width, maxWidth: size.width); dayTextPainter.paint(canvas, Offset(0, 10)); //下面的文字 TextPainter lunarTextPainter = new TextPainter() ..text = new TextSpan( text: dateModel.lunarString, style: new TextStyle( color: !isInRange ? Colors.grey : isWeekend ? Colors.blue : Colors.grey, fontSize: 12)) ..textDirection = TextDirection.ltr ..textAlign = TextAlign.center; lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width); lunarTextPainter.paint(canvas, Offset(0, size.height / 2)); } @override void drawSelected(DateModel dateModel, Canvas canvas, Size size) { if (!dateModel.isCurrentMonth) { return; } //绘制背景 Paint backGroundPaint = new Paint() ..color = Colors.blue ..strokeWidth = 2; double padding = 8; canvas.drawCircle(Offset(size.width / 2, size.height / 2), (size.width - padding) / 2, backGroundPaint); //顶部的文字 TextPainter dayTextPainter = new TextPainter() ..text = TextSpan( text: dateModel.day.toString(), style: new TextStyle(color: Colors.white, fontSize: 16)) ..textDirection = TextDirection.ltr ..textAlign = TextAlign.center; dayTextPainter.layout(minWidth: size.width, maxWidth: size.width); dayTextPainter.paint(canvas, Offset(0, 10)); //下面的文字 TextPainter lunarTextPainter = new TextPainter() ..text = new TextSpan( text: dateModel.lunarString, style: new TextStyle(color: Colors.white, fontSize: 12)) ..textDirection = TextDirection.ltr ..textAlign = TextAlign.center; lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width); lunarTextPainter.paint(canvas, Offset(0, size.height / 2)); } }
然后,我们新建一个date_picker_dialog.dart的Dialog自定义组件,代码如下:
import 'package:flutter/material.dart'; import 'package:gc_data_app/pages/views/gaps.dart'; import 'package:gc_data_app/res/colors.dart'; import 'package:gc_data_app/routes/app_route.dart'; import 'package:gc_data_app/utils/date_utils.dart'; import 'package:gc_data_app/widgets/date_picker_new_widget.dart'; import 'package:gc_data_app/widgets/date_picker_widget.dart'; import 'package:gc_data_app/widgets/drop_down_widget.dart'; import 'package:toast/toast.dart'; class DatePickerDialog extends StatefulWidget { const DatePickerDialog({ Key key, @required this.onSelectedDate, }) : super(key: key); final Function(String) onSelectedDate; @override State<StatefulWidget> createState() { return CustomTimeState(); } } class CustomTimeState extends State<DatePickerDialog> { bool showDate = false; var chooseDateStr = ''; @override Widget build(BuildContext context) { return Material( child: SizedBox( height: 475, child: Container( color: Colors.white, child: Column( children: <Widget>[ _buildTitleBar(), _buildLine(), _buildDatePicker(), ], ), ), ), ); } Widget _buildTitleBar() { return Container( padding: EdgeInsets.only(top: 10, left: 15, bottom: 10, right: 15), child: Row( children: <Widget>[ InkWell( child: Text( '取消', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w300, color: ColorRes.text_little_blue), ), onTap: () { AppRoute.pop(context); }, ), Expanded( child: Center( child: Text( '选择日期', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w300), ), ), ), InkWell( child: Text('确认', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w300, color: ColorRes.text_little_blue)), onTap: () { if(chooseDateStr==''){ Toast.show('选择日期不能为空!', context); return ; } DateTime choose= DateUtils.strToDate(chooseDateStr); DateTime limitStart= DateUtils.strToDate('2014-01-01'); if(choose.isBefore(limitStart)){ Toast.show('起始日期不能早于2014-01-01', context); return ; } widget.onSelectedDate(chooseDateStr); FocusScope.of(context).unfocus(); Navigator.pop(context); }, ) ], ), ); } Widget _buildLine() { return Gaps.line; } Widget _buildDatePicker() { return DatePickerWidget(onSetter: (value) { showDate = false; chooseDateStr = value; }); } }
实际使用时候,使用showCupertinoModalPopup组件展示出来即可,如下所示。
showCalendarSheet(){
showCupertinoModalPopup(
context: context,
builder: (BuildContext context) {
return DatePickerDialog(onSelectedDate: (value){
},
);
},
);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。