mirror of
https://github.com/Iconica-Development/flutter_date_time_picker.git
synced 2025-05-18 18:33:49 +02:00
fix red screen of death caused by overlay not disposing
This commit is contained in:
parent
66e0090597
commit
a3fcfabb01
4 changed files with 134 additions and 104 deletions
|
@ -20,12 +20,7 @@ class MyApp extends StatelessWidget {
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
),
|
),
|
||||||
home: Scaffold(
|
home: const DatePickerDemo(),
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('Demo'),
|
|
||||||
),
|
|
||||||
body: const DatePickerDemo(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,86 +53,99 @@ class DatePickerDemo extends StatelessWidget {
|
||||||
barColor: Colors.black,
|
barColor: Colors.black,
|
||||||
barOpacity: 1,
|
barOpacity: 1,
|
||||||
),
|
),
|
||||||
|
paginationSize: 50,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Stack(
|
return Scaffold(
|
||||||
children: [
|
appBar: AppBar(
|
||||||
Center(
|
automaticallyImplyLeading: true,
|
||||||
child: Column(
|
title: const Text('Demo'),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
),
|
||||||
children: [
|
body: Stack(
|
||||||
OverlayDateTimePicker(
|
children: [
|
||||||
theme: dateTimePickerTheme,
|
Center(
|
||||||
alignment: Alignment.bottomCenter,
|
child: Column(
|
||||||
child: const Text("Select Day"),
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
onTapDay: (date) {},
|
children: [
|
||||||
),
|
OverlayDateTimePicker(
|
||||||
OverlayDateTimePicker(
|
theme: dateTimePickerTheme,
|
||||||
theme: dateTimePickerTheme,
|
alignment: Alignment.bottomCenter,
|
||||||
alignment: Alignment.center,
|
|
||||||
buttonBuilder: (key, onPressed) => TextButton(
|
|
||||||
key: key,
|
|
||||||
onPressed: onPressed,
|
|
||||||
child: const Text("Select Day"),
|
child: const Text("Select Day"),
|
||||||
|
onTapDay: (date) {},
|
||||||
),
|
),
|
||||||
dateTimeConstraint: DateTimeConstraint(
|
OverlayDateTimePicker(
|
||||||
min: DateConstraint(date: DateTime.now()),
|
theme: dateTimePickerTheme,
|
||||||
),
|
alignment: Alignment.center,
|
||||||
),
|
buttonBuilder: (key, onPressed) => TextButton(
|
||||||
OverlayDateTimePicker(
|
key: key,
|
||||||
theme: dateTimePickerTheme,
|
onPressed: onPressed,
|
||||||
alignment: Alignment.topCenter,
|
child: const Text("Select Day"),
|
||||||
buttonBuilder: (key, onPressed) => IconButton(
|
),
|
||||||
key: key,
|
dateTimeConstraint: DateTimeConstraint(
|
||||||
onPressed: onPressed,
|
min: DateConstraint(date: DateTime.now()),
|
||||||
icon: const Icon(
|
|
||||||
Icons.schedule,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dateTimeConstraint: DateTimeConstraint(
|
OverlayDateTimePicker(
|
||||||
min: DateConstraint(date: DateTime.now()),
|
theme: dateTimePickerTheme,
|
||||||
max: DateConstraint(
|
alignment: Alignment.topCenter,
|
||||||
date: DateTime(
|
buttonBuilder: (key, onPressed) => IconButton(
|
||||||
DateTime.now().year,
|
key: key,
|
||||||
DateTime.now().month + 4,
|
onPressed: onPressed,
|
||||||
DateTime.now().day,
|
icon: const Icon(
|
||||||
|
Icons.schedule,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
dateTimeConstraint: DateTimeConstraint(
|
||||||
|
min: DateConstraint(date: DateTime.now()),
|
||||||
|
max: DateConstraint(
|
||||||
|
date: DateTime(
|
||||||
|
DateTime.now().year,
|
||||||
|
DateTime.now().month + 4,
|
||||||
|
DateTime.now().day,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onNextPageButtonBuilder: (onPressed) {
|
||||||
|
return IconButton(
|
||||||
|
onPressed: onPressed, icon: const Icon(Icons.add));
|
||||||
|
},
|
||||||
|
onPreviousPageButtonBuilder: (onPressed) {
|
||||||
|
return IconButton(
|
||||||
|
onPressed: onPressed, icon: const Icon(Icons.minimize));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DragDownDateTimePicker(
|
||||||
|
dateTimePickerTheme: const DateTimePickerTheme(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
markedIndicatorColor: Colors.red,
|
||||||
|
baseTheme: DateBoxBaseTheme(
|
||||||
|
Colors.white,
|
||||||
|
TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
selectedTheme: DateBoxSelectedTheme(
|
||||||
|
Color(0x4BF44336),
|
||||||
|
TextStyle(
|
||||||
|
color: Colors.red,
|
||||||
),
|
),
|
||||||
onNextPageButtonChild: const Icon(Icons.add),
|
),
|
||||||
onPreviousPageButtonChild: const Icon(Icons.minimize),
|
highlightTheme: DateBoxHighlightTheme(
|
||||||
)
|
Colors.red,
|
||||||
],
|
TextStyle(
|
||||||
),
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
DragDownDateTimePicker(
|
),
|
||||||
dateTimePickerTheme: const DateTimePickerTheme(
|
barTheme: DateTimePickerBarTheme(
|
||||||
backgroundColor: Colors.white,
|
barColor: Colors.black,
|
||||||
markedIndicatorColor: Colors.red,
|
barOpacity: 1,
|
||||||
baseTheme: DateBoxBaseTheme(
|
|
||||||
Colors.white,
|
|
||||||
TextStyle(color: Colors.black),
|
|
||||||
),
|
|
||||||
selectedTheme: DateBoxSelectedTheme(
|
|
||||||
Color(0x4BF44336),
|
|
||||||
TextStyle(
|
|
||||||
color: Colors.red,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
highlightTheme: DateBoxHighlightTheme(
|
markedDates: [DateTime(2022, 9, 6)],
|
||||||
Colors.red,
|
)
|
||||||
TextStyle(
|
],
|
||||||
color: Colors.white,
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
barTheme: DateTimePickerBarTheme(
|
|
||||||
barColor: Colors.black,
|
|
||||||
barOpacity: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
markedDates: [DateTime(2022, 9, 6)],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@ import 'package:flutter_date_time_picker/flutter_date_time_picker.dart';
|
||||||
|
|
||||||
class DateTimePickerTheme {
|
class DateTimePickerTheme {
|
||||||
/// The [DateTimePickerTheme] to style [DragDownDateTimePicker] in. Define a custom shape for the dates and specifically style
|
/// The [DateTimePickerTheme] to style [DragDownDateTimePicker] in. Define a custom shape for the dates and specifically style
|
||||||
/// a basic, hightlighted, selected and disabled date.
|
/// a basic, highlighted, selected and disabled date.
|
||||||
const DateTimePickerTheme({
|
const DateTimePickerTheme({
|
||||||
|
this.paginationSize = 25,
|
||||||
this.weekDateBoxSize = 35,
|
this.weekDateBoxSize = 35,
|
||||||
this.monthDateBoxSize = 45,
|
this.monthDateBoxSize = 45,
|
||||||
this.markedIndicatorColor,
|
this.markedIndicatorColor,
|
||||||
|
@ -75,4 +76,7 @@ class DateTimePickerTheme {
|
||||||
|
|
||||||
/// The position where the week view changes to month view and the other way around. Enter a value between 0 and 1 that's between the weekViewSize and the monthViewSize.
|
/// The position where the week view changes to month view and the other way around. Enter a value between 0 and 1 that's between the weekViewSize and the monthViewSize.
|
||||||
final double weekMonthTriggerSize;
|
final double weekMonthTriggerSize;
|
||||||
|
|
||||||
|
/// The size of the buttons for navigation the different pages
|
||||||
|
final double paginationSize;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@ class OverlayDateTimePicker extends StatefulWidget {
|
||||||
this.closeOnSelectDate = true,
|
this.closeOnSelectDate = true,
|
||||||
this.showWeekDays = true,
|
this.showWeekDays = true,
|
||||||
this.dateTimeConstraint = const DateTimeConstraint(),
|
this.dateTimeConstraint = const DateTimeConstraint(),
|
||||||
this.onNextPageButtonChild,
|
this.onNextPageButtonBuilder,
|
||||||
this.onPreviousPageButtonChild,
|
this.onPreviousPageButtonBuilder,
|
||||||
}) : assert(child != null || buttonBuilder != null);
|
}) : assert(child != null || buttonBuilder != null);
|
||||||
|
|
||||||
/// The child contained by the DatePicker.
|
/// The child contained by the DatePicker.
|
||||||
|
@ -84,11 +84,12 @@ class OverlayDateTimePicker extends StatefulWidget {
|
||||||
/// a [DateTimeConstraint] that dictates the constraints of the dates that can be picked.
|
/// a [DateTimeConstraint] that dictates the constraints of the dates that can be picked.
|
||||||
final DateTimeConstraint dateTimeConstraint;
|
final DateTimeConstraint dateTimeConstraint;
|
||||||
|
|
||||||
/// a [Widget] that determents the icon of the button for going to the next page
|
/// a [Function] that determents the icon of the button for going to the next page
|
||||||
final Widget? onNextPageButtonChild;
|
final Widget Function(void Function()? onPressed)? onNextPageButtonBuilder;
|
||||||
|
|
||||||
/// a [Widget] that determents the icon of the button for going to the previous page
|
/// a [Function] that determents the icon of the button for going to the previous page
|
||||||
final Widget? onPreviousPageButtonChild;
|
final Widget Function(void Function()? onPressed)?
|
||||||
|
onPreviousPageButtonBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<OverlayDateTimePicker> createState() => _OverlayDateTimePickerState();
|
State<OverlayDateTimePicker> createState() => _OverlayDateTimePickerState();
|
||||||
|
@ -144,14 +145,15 @@ class _OverlayDateTimePickerState extends State<OverlayDateTimePicker> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
if (_overlay.mounted) _overlay.remove();
|
||||||
_overlay.dispose();
|
_overlay.dispose();
|
||||||
_overlayState?.dispose();
|
_overlayState = null;
|
||||||
_dateTimePickerController.dispose();
|
_dateTimePickerController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _toggleOverlay() {
|
void _toggleOverlay() {
|
||||||
if (mounted) {
|
if (mounted && (_overlayState?.mounted ?? false)) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (!_isShown) {
|
if (!_isShown) {
|
||||||
_overlayState?.insert(_overlay);
|
_overlayState?.insert(_overlay);
|
||||||
|
@ -232,8 +234,8 @@ class _OverlayDateTimePickerState extends State<OverlayDateTimePicker> {
|
||||||
onNextDate: nextDate,
|
onNextDate: nextDate,
|
||||||
onPreviousDate: previousDate,
|
onPreviousDate: previousDate,
|
||||||
dateTimeConstraint: widget.dateTimeConstraint,
|
dateTimeConstraint: widget.dateTimeConstraint,
|
||||||
onNextPageButtonChild: widget.onNextPageButtonChild,
|
onNextPageButtonChild: widget.onNextPageButtonBuilder,
|
||||||
onPreviousPageButtonChild: widget.onPreviousPageButtonChild,
|
onPreviousPageButtonChild: widget.onPreviousPageButtonBuilder,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -32,8 +32,8 @@ class OverlayDateTimeContent extends StatefulWidget {
|
||||||
final bool showWeekDays;
|
final bool showWeekDays;
|
||||||
final DateTimeConstraint dateTimeConstraint;
|
final DateTimeConstraint dateTimeConstraint;
|
||||||
|
|
||||||
final Widget? onNextPageButtonChild;
|
final Widget Function(void Function()? onPressed)? onNextPageButtonChild;
|
||||||
final Widget? onPreviousPageButtonChild;
|
final Widget Function(void Function()? onPressed)? onPreviousPageButtonChild;
|
||||||
|
|
||||||
final void Function() onNextDate;
|
final void Function() onNextDate;
|
||||||
final void Function() onPreviousDate;
|
final void Function() onPreviousDate;
|
||||||
|
@ -77,28 +77,42 @@ class _OverlayDateTimeContentState extends State<OverlayDateTimeContent> {
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
(widget.onPreviousPageButtonChild != null)
|
||||||
onPressed: (widget.dateTimeConstraint.inMonthRange(previousDate))
|
? widget.onPreviousPageButtonChild!(
|
||||||
? _goToPreviousPage
|
(widget.dateTimeConstraint.inMonthRange(previousDate))
|
||||||
: null,
|
? _goToPreviousPage
|
||||||
icon: widget.onPreviousPageButtonChild ??
|
: null,
|
||||||
const Icon(Icons.arrow_circle_left_outlined),
|
)
|
||||||
color: widget.theme.barTheme.barColor,
|
: IconButton(
|
||||||
),
|
onPressed:
|
||||||
|
(widget.dateTimeConstraint.inMonthRange(previousDate))
|
||||||
|
? _goToPreviousPage
|
||||||
|
: null,
|
||||||
|
icon: const Icon(Icons.arrow_circle_left_outlined),
|
||||||
|
color: widget.theme.barTheme.barColor,
|
||||||
|
iconSize: widget.theme.paginationSize,
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
DateFormat.yMMMM().format(
|
DateFormat.yMMMM().format(
|
||||||
widget.controller.browsingDate,
|
widget.controller.browsingDate,
|
||||||
),
|
),
|
||||||
style: widget.theme.baseTheme.textStyle,
|
style: widget.theme.baseTheme.textStyle,
|
||||||
),
|
),
|
||||||
IconButton(
|
(widget.onNextPageButtonChild != null)
|
||||||
onPressed: (widget.dateTimeConstraint.inMonthRange(nextDate))
|
? widget.onNextPageButtonChild!(
|
||||||
? _goToNextPage
|
(widget.dateTimeConstraint.inMonthRange(nextDate))
|
||||||
: null,
|
? _goToNextPage
|
||||||
icon: widget.onNextPageButtonChild ??
|
: null,
|
||||||
const Icon(Icons.arrow_circle_right_outlined),
|
)
|
||||||
color: widget.theme.barTheme.barColor,
|
: IconButton(
|
||||||
),
|
onPressed:
|
||||||
|
(widget.dateTimeConstraint.inMonthRange(nextDate))
|
||||||
|
? _goToNextPage
|
||||||
|
: null,
|
||||||
|
icon: const Icon(Icons.arrow_circle_right_outlined),
|
||||||
|
color: widget.theme.barTheme.barColor,
|
||||||
|
iconSize: widget.theme.paginationSize,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
@ -158,6 +172,7 @@ class _OverlayDateTimeContentState extends State<OverlayDateTimeContent> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _goToNextPage() async {
|
void _goToNextPage() async {
|
||||||
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
usesButtons = true;
|
usesButtons = true;
|
||||||
});
|
});
|
||||||
|
@ -169,6 +184,7 @@ class _OverlayDateTimeContentState extends State<OverlayDateTimeContent> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _goToPreviousPage() async {
|
void _goToPreviousPage() async {
|
||||||
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
usesButtons = true;
|
usesButtons = true;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue