mirror of
https://github.com/nisrulz/flutter-examples.git
synced 2025-11-09 04:58:58 +00:00
New Example - Calendar (#91)
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
||||
|
||||
/// Dialog with some Material colors ([materialColors]) to pick one of them.
|
||||
class ColorPickerDialog extends StatefulWidget {
|
||||
|
||||
/// Initially selected color.
|
||||
///
|
||||
/// If pre-selected color is not from [materialColors] [Colors.blue] will be
|
||||
/// used.
|
||||
final Color selectedColor;
|
||||
|
||||
///
|
||||
const ColorPickerDialog({
|
||||
Key? key,
|
||||
required this.selectedColor
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ColorPickerDialogState();
|
||||
}
|
||||
|
||||
class _ColorPickerDialogState extends State<ColorPickerDialog> {
|
||||
Color _mainColor = Colors.blue;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
bool isSelectedMaterial = materialColors.contains(widget.selectedColor);
|
||||
if (isSelectedMaterial) {
|
||||
_mainColor = widget.selectedColor;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
contentPadding: const EdgeInsets.all(6.0),
|
||||
title: const Text("Color picker"),
|
||||
content: MaterialColorPicker(
|
||||
selectedColor: _mainColor,
|
||||
allowShades: false,
|
||||
onMainColorChange: _onMainColorChange,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('CANCEL'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(null);
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('SUBMIT'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(_mainColor);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _onMainColorChange (Color? newColor) {
|
||||
if (newColor == null) return;
|
||||
|
||||
setState(() {
|
||||
_mainColor = newColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// default with and height for the button container
|
||||
const double _kBtnSize = 24.0;
|
||||
|
||||
/// Round colored button with title to select some style color.
|
||||
class ColorSelectorBtn extends StatelessWidget {
|
||||
/// Title near color button.
|
||||
final String title;
|
||||
|
||||
/// Color of the button.
|
||||
final Color color;
|
||||
|
||||
/// onTap callback.
|
||||
final VoidCallback showDialogFunction;
|
||||
|
||||
/// Size of the circle.
|
||||
///
|
||||
/// By default is [_kBtnSize].
|
||||
final double colorBtnSize;
|
||||
|
||||
///
|
||||
const ColorSelectorBtn(
|
||||
{Key? key,
|
||||
required this.title,
|
||||
required this.color,
|
||||
required this.showDialogFunction,
|
||||
this.colorBtnSize = _kBtnSize})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
GestureDetector(
|
||||
onTap: showDialogFunction,
|
||||
child: Container(
|
||||
height: colorBtnSize,
|
||||
width: colorBtnSize,
|
||||
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart' as dp;
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart';
|
||||
|
||||
import '../color_picker_dialog.dart';
|
||||
import '../color_selector_btn.dart';
|
||||
import '../event.dart';
|
||||
|
||||
/// Page with [dp.DayPicker].
|
||||
class DayPickerPage extends StatefulWidget {
|
||||
/// Custom events.
|
||||
final List<Event> events;
|
||||
|
||||
///
|
||||
const DayPickerPage({
|
||||
Key? key,
|
||||
this.events = const []
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DayPickerPageState();
|
||||
}
|
||||
|
||||
class _DayPickerPageState extends State<DayPickerPage> {
|
||||
DateTime _selectedDate = DateTime.now();
|
||||
|
||||
DateTime _firstDate = DateTime.now().subtract(Duration(days: 45));
|
||||
DateTime _lastDate = DateTime.now().add(Duration(days: 45));
|
||||
|
||||
Color selectedDateStyleColor = Colors.blue;
|
||||
Color selectedSingleDateDecorationColor = Colors.red;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
Color? bodyTextColor = Theme.of(context).accentTextTheme.bodyText1?.color;
|
||||
if (bodyTextColor != null) selectedDateStyleColor = bodyTextColor;
|
||||
|
||||
selectedSingleDateDecorationColor = Theme.of(context).accentColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// add selected colors to default settings
|
||||
dp.DatePickerRangeStyles styles = dp.DatePickerRangeStyles(
|
||||
selectedDateStyle: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: selectedDateStyleColor),
|
||||
selectedSingleDateDecoration: BoxDecoration(
|
||||
color: selectedSingleDateDecorationColor,
|
||||
shape: BoxShape.circle
|
||||
),
|
||||
dayHeaderStyle: DayHeaderStyle(
|
||||
textStyle: TextStyle(
|
||||
color: Colors.red
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return Flex(
|
||||
direction: MediaQuery.of(context).orientation == Orientation.portrait
|
||||
? Axis.vertical
|
||||
: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: dp.DayPicker.single(
|
||||
selectedDate: _selectedDate,
|
||||
onChanged: _onSelectedDateChanged,
|
||||
firstDate: _firstDate,
|
||||
lastDate: _lastDate,
|
||||
datePickerStyles: styles,
|
||||
datePickerLayoutSettings: dp.DatePickerLayoutSettings(
|
||||
maxDayPickerRowCount: 2,
|
||||
showPrevMonthEnd: true,
|
||||
showNextMonthStart: true
|
||||
),
|
||||
selectableDayPredicate: _isSelectableCustom,
|
||||
eventDecorationBuilder: _eventDecorationBuilder,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Selected date styles",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ColorSelectorBtn(
|
||||
title: "Text",
|
||||
color: selectedDateStyleColor,
|
||||
showDialogFunction: _showSelectedDateDialog,
|
||||
colorBtnSize: 42.0,
|
||||
),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "Background",
|
||||
color: selectedSingleDateDecorationColor,
|
||||
showDialogFunction: _showSelectedBackgroundColorDialog,
|
||||
colorBtnSize: 42.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Selected: $_selectedDate")
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// select text color of the selected date
|
||||
void _showSelectedDateDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedDateStyleColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedDateStyleColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color of the selected date
|
||||
void _showSelectedBackgroundColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedSingleDateDecorationColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedSingleDateDecorationColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectedDateChanged(DateTime newDate) {
|
||||
setState(() {
|
||||
_selectedDate = newDate;
|
||||
});
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
bool _isSelectableCustom (DateTime day) {
|
||||
return day.weekday < 6;
|
||||
}
|
||||
|
||||
dp.EventDecoration? _eventDecorationBuilder(DateTime date) {
|
||||
List<DateTime> eventsDates = widget.events
|
||||
.map<DateTime>((Event e) => e.date)
|
||||
.toList();
|
||||
|
||||
bool isEventDate = eventsDates.any((DateTime d) =>
|
||||
date.year == d.year
|
||||
&& date.month == d.month
|
||||
&& d.day == date.day);
|
||||
|
||||
BoxDecoration roundedBorder = BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.deepOrange,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(3.0))
|
||||
);
|
||||
|
||||
return isEventDate
|
||||
? dp.EventDecoration(boxDecoration: roundedBorder)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart' as dp;
|
||||
|
||||
import '../color_picker_dialog.dart';
|
||||
import '../color_selector_btn.dart';
|
||||
import '../event.dart';
|
||||
|
||||
/// Page with [dp.DayPicker] where many single days can be selected.
|
||||
class DaysPickerPage extends StatefulWidget {
|
||||
/// Custom events.
|
||||
final List<Event> events;
|
||||
|
||||
///
|
||||
const DaysPickerPage({
|
||||
Key? key,
|
||||
this.events = const []
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DaysPickerPageState();
|
||||
}
|
||||
|
||||
class _DaysPickerPageState extends State<DaysPickerPage> {
|
||||
List<DateTime> _selectedDates = [];
|
||||
DateTime _firstDate = DateTime.now().subtract(Duration(days: 45));
|
||||
DateTime _lastDate = DateTime.now().add(Duration(days: 45));
|
||||
|
||||
Color selectedDateStyleColor = Colors.blue;
|
||||
Color selectedSingleDateDecorationColor = Colors.red;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final now = DateTime.now();
|
||||
|
||||
_selectedDates = [
|
||||
now,
|
||||
now.subtract(Duration(days: 10)),
|
||||
now.add(Duration(days: 7))
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
Color? bodyTextColor = Theme.of(context).accentTextTheme.bodyText1?.color;
|
||||
if (bodyTextColor != null) selectedDateStyleColor = bodyTextColor;
|
||||
|
||||
selectedSingleDateDecorationColor = Theme.of(context).accentColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// add selected colors to default settings
|
||||
dp.DatePickerRangeStyles styles = dp.DatePickerRangeStyles(
|
||||
selectedDateStyle: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: selectedDateStyleColor),
|
||||
selectedSingleDateDecoration: BoxDecoration(
|
||||
color: selectedSingleDateDecorationColor, shape: BoxShape.circle));
|
||||
|
||||
return Flex(
|
||||
direction: MediaQuery.of(context).orientation == Orientation.portrait
|
||||
? Axis.vertical
|
||||
: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: dp.DayPicker.multi(
|
||||
selectedDates: _selectedDates,
|
||||
onChanged: _onSelectedDateChanged,
|
||||
firstDate: _firstDate,
|
||||
lastDate: _lastDate,
|
||||
datePickerStyles: styles,
|
||||
datePickerLayoutSettings: dp.DatePickerLayoutSettings(
|
||||
maxDayPickerRowCount: 2,
|
||||
showPrevMonthEnd: true,
|
||||
showNextMonthStart: true
|
||||
),
|
||||
selectableDayPredicate: _isSelectableCustom,
|
||||
eventDecorationBuilder: _eventDecorationBuilder,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Selected date styles",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ColorSelectorBtn(
|
||||
title: "Text",
|
||||
color: selectedDateStyleColor,
|
||||
showDialogFunction: _showSelectedDateDialog,
|
||||
colorBtnSize: 42.0,
|
||||
),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "Background",
|
||||
color: selectedSingleDateDecorationColor,
|
||||
showDialogFunction: _showSelectedBackgroundColorDialog,
|
||||
colorBtnSize: 42.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Selected: $_selectedDates")
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// select text color of the selected date
|
||||
void _showSelectedDateDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedDateStyleColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedDateStyleColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color of the selected date
|
||||
void _showSelectedBackgroundColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedSingleDateDecorationColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedSingleDateDecorationColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectedDateChanged(List<DateTime> newDates) {
|
||||
setState(() {
|
||||
_selectedDates = newDates;
|
||||
});
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
bool _isSelectableCustom (DateTime day) {
|
||||
return day.weekday < 6;
|
||||
}
|
||||
|
||||
dp.EventDecoration? _eventDecorationBuilder(DateTime date) {
|
||||
List<DateTime> eventsDates = widget.events
|
||||
.map<DateTime>((Event e) => e.date)
|
||||
.toList();
|
||||
|
||||
bool isEventDate = eventsDates.any((DateTime d) =>
|
||||
date.year == d.year
|
||||
&& date.month == d.month
|
||||
&& d.day == date.day);
|
||||
|
||||
BoxDecoration roundedBorder = BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.deepOrange,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(3.0))
|
||||
);
|
||||
|
||||
return isEventDate
|
||||
? dp.EventDecoration(boxDecoration: roundedBorder)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart' as dp;
|
||||
|
||||
import '../color_picker_dialog.dart';
|
||||
import '../color_selector_btn.dart';
|
||||
|
||||
/// Page with the [dp.MonthPicker].
|
||||
class MonthPickerPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MonthPickerPageState();
|
||||
}
|
||||
|
||||
class _MonthPickerPageState extends State<MonthPickerPage> {
|
||||
DateTime _firstDate = DateTime.now().subtract(Duration(days: 350));
|
||||
DateTime _lastDate = DateTime.now().add(Duration(days: 350));
|
||||
DateTime _selectedDate = DateTime.now();
|
||||
|
||||
Color selectedDateStyleColor = Colors.blue;
|
||||
Color selectedSingleDateDecorationColor = Colors.red;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
Color? bodyTextColor = Theme.of(context).accentTextTheme.bodyText1?.color;
|
||||
if (bodyTextColor != null) selectedDateStyleColor = bodyTextColor;
|
||||
|
||||
selectedSingleDateDecorationColor = Theme.of(context).accentColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// add selected colors to default settings
|
||||
dp.DatePickerStyles styles = dp.DatePickerStyles(
|
||||
selectedDateStyle: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: selectedDateStyleColor),
|
||||
selectedSingleDateDecoration: BoxDecoration(
|
||||
color: selectedSingleDateDecorationColor, shape: BoxShape.circle));
|
||||
|
||||
return Flex(
|
||||
direction: MediaQuery.of(context).orientation == Orientation.portrait
|
||||
? Axis.vertical
|
||||
: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: dp.MonthPicker(
|
||||
selectedDate: _selectedDate,
|
||||
onChanged: _onSelectedDateChanged,
|
||||
firstDate: _firstDate,
|
||||
lastDate: _lastDate,
|
||||
datePickerStyles: styles,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Selected date styles",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ColorSelectorBtn(
|
||||
title: "Text",
|
||||
color: selectedDateStyleColor,
|
||||
showDialogFunction: _showSelectedDateDialog,
|
||||
colorBtnSize: 42.0,
|
||||
),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "Background",
|
||||
color: selectedSingleDateDecorationColor,
|
||||
showDialogFunction: _showSelectedBackgroundColorDialog,
|
||||
colorBtnSize: 42.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Selected: $_selectedDate")
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// select text color of the selected date
|
||||
void _showSelectedDateDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedDateStyleColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedDateStyleColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color of the selected date
|
||||
void _showSelectedBackgroundColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedSingleDateDecorationColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedSingleDateDecorationColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectedDateChanged(DateTime newDate) {
|
||||
setState(() {
|
||||
_selectedDate = newDate;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart';
|
||||
|
||||
import '../color_picker_dialog.dart';
|
||||
import '../color_selector_btn.dart';
|
||||
import '../event.dart';
|
||||
|
||||
/// Page with the [RangePicker].
|
||||
class RangePickerPage extends StatefulWidget {
|
||||
|
||||
/// Custom events.
|
||||
final List<Event> events;
|
||||
|
||||
///
|
||||
const RangePickerPage({
|
||||
Key? key,
|
||||
this.events = const []
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _RangePickerPageState();
|
||||
}
|
||||
|
||||
class _RangePickerPageState extends State<RangePickerPage> {
|
||||
DateTime _firstDate = DateTime.now().subtract(Duration(days: 345));
|
||||
DateTime _lastDate = DateTime.now().add(Duration(days: 345));
|
||||
DatePeriod _selectedPeriod = DatePeriod(
|
||||
DateTime.now().subtract(Duration(days: 30)),
|
||||
DateTime.now().subtract(Duration(days: 12))
|
||||
);
|
||||
|
||||
Color selectedPeriodStartColor = Colors.blue;
|
||||
Color selectedPeriodLastColor = Colors.blue;
|
||||
Color selectedPeriodMiddleColor = Colors.blue;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
selectedPeriodLastColor = Theme.of(context).accentColor;
|
||||
selectedPeriodMiddleColor = Theme.of(context).accentColor;
|
||||
selectedPeriodStartColor = Theme.of(context).accentColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// add selected colors to default settings
|
||||
DatePickerRangeStyles styles = DatePickerRangeStyles(
|
||||
selectedPeriodLastDecoration: BoxDecoration(
|
||||
color: selectedPeriodLastColor,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(24.0),
|
||||
bottomRight: Radius.circular(24.0))),
|
||||
selectedPeriodStartDecoration: BoxDecoration(
|
||||
color: selectedPeriodStartColor,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(24.0),
|
||||
bottomLeft: Radius.circular(24.0)
|
||||
),
|
||||
),
|
||||
selectedPeriodMiddleDecoration: BoxDecoration(
|
||||
color: selectedPeriodMiddleColor, shape: BoxShape.rectangle),
|
||||
nextIcon: const Icon(Icons.arrow_right),
|
||||
prevIcon: const Icon(Icons.arrow_left),
|
||||
dayHeaderStyleBuilder: _dayHeaderStyleBuilder
|
||||
);
|
||||
|
||||
return Flex(
|
||||
direction: MediaQuery.of(context).orientation == Orientation.portrait
|
||||
? Axis.vertical
|
||||
: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: RangePicker(
|
||||
initiallyShowDate: DateTime.now(),
|
||||
selectedPeriod: _selectedPeriod,
|
||||
onChanged: _onSelectedDateChanged,
|
||||
firstDate: _firstDate,
|
||||
lastDate: _lastDate,
|
||||
datePickerStyles: styles,
|
||||
eventDecorationBuilder: _eventDecorationBuilder,
|
||||
selectableDayPredicate: _isSelectableCustom,
|
||||
onSelectionError: _onSelectionError,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Selected date styles",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
_stylesBlock(),
|
||||
_selectedBlock()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Block with show information about selected date
|
||||
// and boundaries of the selected period.
|
||||
Widget _selectedBlock() => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_selectedPeriod != null
|
||||
? Column(children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0, bottom: 4.0),
|
||||
child: Text("Selected period boundaries:"),
|
||||
),
|
||||
Text(_selectedPeriod.start.toString()),
|
||||
Text(_selectedPeriod.end.toString()),
|
||||
])
|
||||
: Container()
|
||||
],
|
||||
);
|
||||
|
||||
// block with color buttons inside
|
||||
Widget _stylesBlock() => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ColorSelectorBtn(
|
||||
title: "Start",
|
||||
color: selectedPeriodStartColor,
|
||||
showDialogFunction: _showSelectedStartColorDialog),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "Middle",
|
||||
color: selectedPeriodMiddleColor,
|
||||
showDialogFunction: _showSelectedMiddleColorDialog),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "End",
|
||||
color: selectedPeriodLastColor,
|
||||
showDialogFunction: _showSelectedEndColorDialog),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// select background color for the first date of the selected period
|
||||
void _showSelectedStartColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedPeriodStartColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedPeriodStartColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color for the last date of the selected period
|
||||
void _showSelectedEndColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedPeriodLastColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedPeriodLastColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color for the middle dates of the selected period
|
||||
void _showSelectedMiddleColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedPeriodMiddleColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedPeriodMiddleColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectedDateChanged(DatePeriod newPeriod) {
|
||||
setState(() {
|
||||
_selectedPeriod = newPeriod;
|
||||
});
|
||||
}
|
||||
|
||||
EventDecoration? _eventDecorationBuilder(DateTime date) {
|
||||
List<DateTime> eventsDates = widget.events
|
||||
.map<DateTime>((Event e) => e.date)
|
||||
.toList();
|
||||
|
||||
bool isEventDate = eventsDates.any((DateTime d) =>
|
||||
date.year == d.year
|
||||
&& date.month == d.month
|
||||
&& d.day == date.day);
|
||||
|
||||
BoxDecoration roundedBorder = BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.green,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(3.0))
|
||||
);
|
||||
|
||||
return isEventDate
|
||||
? EventDecoration(boxDecoration: roundedBorder)
|
||||
: null;
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
bool _isSelectableCustom (DateTime day) {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime yesterday = now.subtract(Duration(days: 1));
|
||||
DateTime tomorrow = now.add(Duration(days: 1));
|
||||
bool isYesterday = sameDate(day, yesterday);
|
||||
bool isTomorrow = sameDate(day, tomorrow);
|
||||
|
||||
return !isYesterday && !isTomorrow;
|
||||
|
||||
// return true;
|
||||
// return day.weekday < 6;
|
||||
// return day.day != DateTime.now().add(Duration(days: 7)).day ;
|
||||
}
|
||||
|
||||
void _onSelectionError(UnselectablePeriodException exception) {
|
||||
DatePeriod errorPeriod = exception.period;
|
||||
|
||||
// If user supposed to set another start of the period.
|
||||
bool selectStart = _selectedPeriod.start != errorPeriod.start;
|
||||
|
||||
DateTime newSelection = selectStart
|
||||
? errorPeriod.start
|
||||
: errorPeriod.end;
|
||||
|
||||
DatePeriod newPeriod = DatePeriod(newSelection, newSelection);
|
||||
|
||||
setState(() {
|
||||
_selectedPeriod = newPeriod;
|
||||
});
|
||||
}
|
||||
|
||||
// 0 is Sunday, 6 is Saturday
|
||||
DayHeaderStyle _dayHeaderStyleBuilder(int weekday) {
|
||||
bool isWeekend = weekday == 0 || weekday == 6;
|
||||
|
||||
return DayHeaderStyle(
|
||||
textStyle: TextStyle(
|
||||
color: isWeekend ? Colors.red : Colors.teal
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool sameDate(DateTime first, DateTime second) {
|
||||
return first.year == second.year && first.month == second.month && first.day == second.day;
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart';
|
||||
|
||||
import '../event.dart';
|
||||
|
||||
/// Page with the [RangePicker] styled according to issue:
|
||||
/// https://github.com/MariaMelnik/flutter_date_pickers/issues/49
|
||||
class RangePickerPageStyled extends StatefulWidget {
|
||||
|
||||
/// Custom events.
|
||||
final List<Event> events;
|
||||
|
||||
///
|
||||
const RangePickerPageStyled({
|
||||
Key? key,
|
||||
this.events = const []
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _RangePickerPageStyledState();
|
||||
}
|
||||
|
||||
class _RangePickerPageStyledState extends State<RangePickerPageStyled> {
|
||||
DateTime _firstDate = DateTime.now().subtract(Duration(days: 345));
|
||||
DateTime _lastDate = DateTime.now().add(Duration(days: 345));
|
||||
DatePeriod _selectedPeriod = DatePeriod(
|
||||
DateTime.now().subtract(Duration(days: 4)),
|
||||
DateTime.now().add(Duration(days: 8))
|
||||
);
|
||||
|
||||
Color selectedPeriodStartColor = Colors.blue;
|
||||
Color selectedPeriodLastColor = Colors.blue;
|
||||
Color selectedPeriodMiddleColor = Colors.blue;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
DateTime selectedPeriodStart = DateTime.now().subtract(Duration(days: 4));
|
||||
DateTime selectedPeriodEnd = DateTime.now().add(Duration(days: 8));
|
||||
_selectedPeriod = DatePeriod(selectedPeriodStart, selectedPeriodEnd);
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
// defaults for styles
|
||||
selectedPeriodLastColor = Theme.of(context).accentColor;
|
||||
selectedPeriodMiddleColor = Theme.of(context).accentColor;
|
||||
selectedPeriodStartColor = Theme.of(context).accentColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color middleBgColor = Color.fromRGBO(237, 237, 250, 1);
|
||||
DecorationImage circleImg = DecorationImage(
|
||||
image: AssetImage('images/bg.png'),
|
||||
fit: BoxFit.contain
|
||||
);
|
||||
|
||||
// add selected colors to default settings
|
||||
DatePickerRangeStyles styles = DatePickerRangeStyles(
|
||||
selectedPeriodLastDecoration: BoxDecoration(
|
||||
color: middleBgColor,
|
||||
gradient: LinearGradient(
|
||||
colors: [middleBgColor, Colors.transparent],
|
||||
stops: [0.5, 0.5]
|
||||
),
|
||||
image: circleImg,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(24.0),
|
||||
bottomRight: Radius.circular(24.0))
|
||||
),
|
||||
selectedPeriodStartDecoration: BoxDecoration(
|
||||
color: middleBgColor,
|
||||
gradient: LinearGradient(
|
||||
colors: [Colors.transparent, middleBgColor,],
|
||||
stops: [0.5, 0.5]
|
||||
),
|
||||
image: circleImg,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(24.0),
|
||||
bottomLeft: Radius.circular(24.0)
|
||||
),
|
||||
),
|
||||
selectedPeriodMiddleDecoration: BoxDecoration(
|
||||
color: middleBgColor,
|
||||
shape: BoxShape.rectangle
|
||||
),
|
||||
);
|
||||
|
||||
return Flex(
|
||||
direction: MediaQuery.of(context).orientation == Orientation.portrait
|
||||
? Axis.vertical
|
||||
: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: RangePicker(
|
||||
selectedPeriod: _selectedPeriod,
|
||||
onChanged: _onSelectedDateChanged,
|
||||
firstDate: _firstDate,
|
||||
lastDate: _lastDate,
|
||||
datePickerStyles: styles,
|
||||
eventDecorationBuilder: _eventDecorationBuilder,
|
||||
selectableDayPredicate: _isSelectableCustom,
|
||||
onSelectionError: _onSelectionError,
|
||||
datePickerLayoutSettings: DatePickerLayoutSettings(
|
||||
showNextMonthStart: true,
|
||||
showPrevMonthEnd: true
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Selected date styles",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
_selectedBlock()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Block with show information about selected date
|
||||
// and boundaries of the selected period.
|
||||
Widget _selectedBlock() => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_selectedPeriod != null
|
||||
? Column(children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0, bottom: 4.0),
|
||||
child: Text("Selected period boundaries:"),
|
||||
),
|
||||
Text(_selectedPeriod.start.toString()),
|
||||
Text(_selectedPeriod.end.toString()),
|
||||
])
|
||||
: Container()
|
||||
],
|
||||
);
|
||||
|
||||
void _onSelectedDateChanged(DatePeriod newPeriod) {
|
||||
setState(() {
|
||||
_selectedPeriod = newPeriod;
|
||||
});
|
||||
}
|
||||
|
||||
EventDecoration? _eventDecorationBuilder(DateTime date) {
|
||||
List<DateTime> eventsDates = widget.events
|
||||
.map<DateTime>((Event e) => e.date)
|
||||
.toList();
|
||||
|
||||
bool isEventDate = eventsDates.any((DateTime d) =>
|
||||
date.year == d.year
|
||||
&& date.month == d.month
|
||||
&& d.day == date.day);
|
||||
|
||||
BoxDecoration roundedBorder = BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.green,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(3.0))
|
||||
);
|
||||
|
||||
return isEventDate
|
||||
? EventDecoration(boxDecoration: roundedBorder)
|
||||
: null;
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
bool _isSelectableCustom (DateTime day) {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime yesterday = now.subtract(Duration(days: 1));
|
||||
DateTime tomorrow = now.add(Duration(days: 1));
|
||||
bool isYesterday = _sameDate(day, yesterday);
|
||||
bool isTomorrow = _sameDate(day, tomorrow);
|
||||
|
||||
return !isYesterday && !isTomorrow;
|
||||
|
||||
// return true;
|
||||
// return day.weekday < 6;
|
||||
// return day.day != DateTime.now().add(Duration(days: 7)).day ;
|
||||
}
|
||||
|
||||
void _onSelectionError(UnselectablePeriodException exception) {
|
||||
DatePeriod errorPeriod = exception.period;
|
||||
|
||||
// If user supposed to set another start of the period.
|
||||
bool selectStart = _selectedPeriod.start != errorPeriod.start;
|
||||
|
||||
DateTime newSelection = selectStart
|
||||
? errorPeriod.start
|
||||
: errorPeriod.end;
|
||||
|
||||
DatePeriod newPeriod = DatePeriod(newSelection, newSelection);
|
||||
|
||||
setState(() {
|
||||
_selectedPeriod = newPeriod;
|
||||
});
|
||||
}
|
||||
|
||||
// 0 is Sunday, 6 is Saturday
|
||||
DayHeaderStyle _dayHeaderStyleBuilder(int weekday) {
|
||||
bool isWeekend = weekday == 0 || weekday == 6;
|
||||
|
||||
return DayHeaderStyle(
|
||||
textStyle: TextStyle(
|
||||
color: isWeekend ? Colors.red : Colors.teal
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _sameDate(DateTime first, DateTime second) =>
|
||||
first.year == second.year
|
||||
&& first.month == second.month
|
||||
&& first.day == second.day;
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_pickers/flutter_date_pickers.dart';
|
||||
|
||||
import '../color_picker_dialog.dart';
|
||||
import '../color_selector_btn.dart';
|
||||
import '../event.dart';
|
||||
|
||||
/// Page with the [WeekPicker].
|
||||
class WeekPickerPage extends StatefulWidget {
|
||||
/// Custom events.
|
||||
final List<Event> events;
|
||||
|
||||
///
|
||||
const WeekPickerPage({
|
||||
Key? key,
|
||||
this.events = const []
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _WeekPickerPageState();
|
||||
}
|
||||
|
||||
class _WeekPickerPageState extends State<WeekPickerPage> {
|
||||
DateTime _selectedDate = DateTime.now();
|
||||
DateTime _firstDate = DateTime.now().subtract(Duration(days: 45));
|
||||
DateTime _lastDate = DateTime.now().add(Duration(days: 45));
|
||||
DatePeriod? _selectedPeriod;
|
||||
|
||||
Color selectedPeriodStartColor = Colors.blue;
|
||||
Color selectedPeriodLastColor = Colors.blue;
|
||||
Color selectedPeriodMiddleColor = Colors.blue;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
// defaults for styles
|
||||
selectedPeriodLastColor = Theme.of(context).accentColor;
|
||||
selectedPeriodMiddleColor = Theme.of(context).accentColor;
|
||||
selectedPeriodStartColor = Theme.of(context).accentColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// add selected colors to default settings
|
||||
DatePickerRangeStyles styles = DatePickerRangeStyles(
|
||||
selectedPeriodLastDecoration: BoxDecoration(
|
||||
color: selectedPeriodLastColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(10.0),
|
||||
bottomRight: Radius.circular(10.0))),
|
||||
selectedPeriodStartDecoration: BoxDecoration(
|
||||
color: selectedPeriodStartColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(10.0), bottomLeft: Radius.circular(10.0)),
|
||||
),
|
||||
selectedPeriodMiddleDecoration: BoxDecoration(
|
||||
color: selectedPeriodMiddleColor, shape: BoxShape.rectangle),
|
||||
);
|
||||
|
||||
return Flex(
|
||||
direction: MediaQuery.of(context).orientation == Orientation.portrait
|
||||
? Axis.vertical
|
||||
: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: WeekPicker(
|
||||
selectedDate: _selectedDate,
|
||||
onChanged: _onSelectedDateChanged,
|
||||
firstDate: _firstDate,
|
||||
lastDate: _lastDate,
|
||||
datePickerStyles: styles,
|
||||
onSelectionError: _onSelectionError,
|
||||
selectableDayPredicate: _isSelectableCustom,
|
||||
eventDecorationBuilder: _eventDecorationBuilder,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Selected date styles",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
_stylesBlock(),
|
||||
_selectedBlock()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// block witt color buttons insede
|
||||
Widget _stylesBlock() => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ColorSelectorBtn(
|
||||
title: "Start",
|
||||
color: selectedPeriodStartColor,
|
||||
showDialogFunction: _showSelectedStartColorDialog),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "Middle",
|
||||
color: selectedPeriodMiddleColor,
|
||||
showDialogFunction: _showSelectedMiddleColorDialog),
|
||||
SizedBox(
|
||||
width: 12.0,
|
||||
),
|
||||
ColorSelectorBtn(
|
||||
title: "End",
|
||||
color: selectedPeriodLastColor,
|
||||
showDialogFunction: _showSelectedEndColorDialog),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Block with information about selected date
|
||||
// and boundaries of the selected period.
|
||||
Widget _selectedBlock() => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text("Selected: $_selectedDate"),
|
||||
),
|
||||
_selectedPeriod != null
|
||||
? Column(children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0, bottom: 4.0),
|
||||
child: Text("Selected period boundaries:"),
|
||||
),
|
||||
Text(_selectedPeriod!.start.toString()),
|
||||
Text(_selectedPeriod!.end.toString()),
|
||||
])
|
||||
: Container()
|
||||
],
|
||||
);
|
||||
|
||||
// select background color for the first date of the selected period
|
||||
void _showSelectedStartColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedPeriodStartColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedPeriodStartColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color for the last date of the selected period
|
||||
void _showSelectedEndColorDialog() async {
|
||||
Color? newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedPeriodLastColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedPeriodLastColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// select background color for the middle dates of the selected period
|
||||
void _showSelectedMiddleColorDialog() async {
|
||||
Color newSelectedColor = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => ColorPickerDialog(
|
||||
selectedColor: selectedPeriodMiddleColor,
|
||||
));
|
||||
|
||||
if (newSelectedColor != null) {
|
||||
setState(() {
|
||||
selectedPeriodMiddleColor = newSelectedColor;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectedDateChanged(DatePeriod newPeriod) {
|
||||
setState(() {
|
||||
_selectedDate = newPeriod.start;
|
||||
_selectedPeriod = newPeriod;
|
||||
});
|
||||
}
|
||||
|
||||
void _onSelectionError(Object e){
|
||||
if (e is UnselectablePeriodException) print("catch error: $e");
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
bool _isSelectableCustom (DateTime day) {
|
||||
// return day.weekday < 6;
|
||||
return day.day != DateTime.now().add(Duration(days: 7)).day ;
|
||||
}
|
||||
|
||||
EventDecoration? _eventDecorationBuilder(DateTime date) {
|
||||
List<DateTime> eventsDates = widget.events
|
||||
.map<DateTime>((Event e) => e.date)
|
||||
.toList();
|
||||
|
||||
bool isEventDate = eventsDates.any((DateTime d) => date.year == d.year
|
||||
&& date.month == d.month
|
||||
&& d.day == date.day);
|
||||
|
||||
if (!isEventDate) return null;
|
||||
|
||||
BoxDecoration roundedBorder = BoxDecoration(
|
||||
color: Colors.blue,
|
||||
border: Border.all(
|
||||
color: Colors.blue,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(3.0))
|
||||
);
|
||||
|
||||
TextStyle? whiteText = Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2
|
||||
?.copyWith(color: Colors.white);
|
||||
|
||||
return isEventDate
|
||||
? EventDecoration(boxDecoration: roundedBorder, textStyle: whiteText)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
14
flutter_date_pickers-master/example/lib/event.dart
Normal file
14
flutter_date_pickers-master/example/lib/event.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
/// Event for the date pickers.
|
||||
class Event {
|
||||
|
||||
/// Event's date.
|
||||
final DateTime date;
|
||||
|
||||
/// Event's title.
|
||||
final String dis;
|
||||
|
||||
///
|
||||
Event(this.date, this.dis)
|
||||
: assert(date != null),
|
||||
assert(dis != null);
|
||||
}
|
||||
121
flutter_date_pickers-master/example/lib/main.dart
Normal file
121
flutter_date_pickers-master/example/lib/main.dart
Normal file
@@ -0,0 +1,121 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'date_pickers_widgets/day_picker_page.dart';
|
||||
import 'date_pickers_widgets/days_picker_page.dart';
|
||||
import 'date_pickers_widgets/month_picker_page.dart';
|
||||
import 'date_pickers_widgets/range_picker_page.dart';
|
||||
import 'date_pickers_widgets/week_picker_page.dart';
|
||||
|
||||
import 'event.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
///
|
||||
class MyApp extends StatelessWidget {
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
localizationsDelegates: GlobalMaterialLocalizations.delegates,
|
||||
supportedLocales: [
|
||||
const Locale('en', 'US'), // American English
|
||||
const Locale('ru', 'RU'), // Russian
|
||||
const Locale("pt") // Portuguese
|
||||
],
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'Date pickers demo',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blueGrey,
|
||||
),
|
||||
home: MyHomePage(
|
||||
title: 'flutter_date_pickers Demo',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Start page.
|
||||
class MyHomePage extends StatefulWidget {
|
||||
/// Page title.
|
||||
final String title;
|
||||
|
||||
///
|
||||
MyHomePage({
|
||||
required this.title,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyHomePageState createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
|
||||
DateTime startOfPeriod = DateTime.now().subtract(Duration(days: 10));
|
||||
DateTime endOfPeriod = DateTime.now().add(Duration(days: 10));
|
||||
int _selectedTab = 0;
|
||||
|
||||
final List<Widget> datePickers = <Widget>[
|
||||
DayPickerPage(events: events,),
|
||||
DaysPickerPage(),
|
||||
WeekPickerPage(events: events,),
|
||||
RangePickerPage(events: events,),
|
||||
MonthPickerPage()
|
||||
];
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
widget.title,
|
||||
style: TextStyle(letterSpacing: 1.15),
|
||||
),
|
||||
),
|
||||
body: datePickers[_selectedTab],
|
||||
bottomNavigationBar: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
canvasColor: Colors.blueGrey,
|
||||
textTheme: Theme.of(context).textTheme.copyWith(
|
||||
caption: TextStyle(color: Colors.white.withOpacity(0.5)))),
|
||||
child: BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.date_range), label: "Day"),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.date_range), label: "Days"),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.date_range), label: "Week"),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.date_range), label: "Range"),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.date_range), label: "Month"),
|
||||
],
|
||||
fixedColor: Colors.yellow,
|
||||
currentIndex: _selectedTab,
|
||||
onTap: (newIndex) {
|
||||
setState(() {
|
||||
_selectedTab = newIndex;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Mock events.
|
||||
final List<Event> events = [
|
||||
Event(DateTime.now(), "Today event"),
|
||||
Event(DateTime.now().subtract(Duration(days: 3)), "Ev1"),
|
||||
Event(DateTime.now().subtract(Duration(days: 13)), "Ev2"),
|
||||
Event(DateTime.now().subtract(Duration(days: 30)), "Ev3"),
|
||||
Event(DateTime.now().add(Duration(days: 3)), "Ev4"),
|
||||
Event(DateTime.now().add(Duration(days: 13)), "Ev5"),
|
||||
Event(DateTime.now().add(Duration(days: 30)), "Ev6"),
|
||||
];
|
||||
Reference in New Issue
Block a user