// import 'dart:async'; // import 'dart:math' as math; // // import 'package:flutter/gestures.dart' show DragStartBehavior; // import 'package:flutter/material.dart'; // import 'package:flutter/rendering.dart'; // import 'package:flutter/services.dart'; // import 'package:flutter/widgets.dart'; // // import 'button_actions.dart'; // import 'era_mode.dart'; // // /// Initial display mode of the date picker dialog. // /// // /// Date picker UI mode for either showing a list of available years or a // /// monthly calendar initially in the dialog shown by calling [showDatePicker]. // /// // // const Duration _kMonthScrollDuration = Duration(milliseconds: 200); // const double _kDayPickerRowHeight = 42.0; // const int _kMaxDayPickerRowCount = 6; // A 31 day month that starts on Saturday. // // Two extra rows: one for the day-of-week header and one for the month header. // const double _kMaxDayPickerHeight = // _kDayPickerRowHeight * (_kMaxDayPickerRowCount + 2); // // /// Shows the selected date in large font and toggles between year and day mode // class _DatePickerHeader extends StatelessWidget { // const _DatePickerHeader({ // Key key, // @required this.selectedDate, // @required this.mode, // @required this.onModeChanged, // @required this.orientation, // this.yearSelectAllowed, // this.era, // this.borderRadius, // this.imageHeader, // this.description = "", // this.fontFamily, // }) : assert(selectedDate != null), // assert(mode != null), // assert(orientation != null), // super(key: key); // // final DateTime selectedDate; // final DatePickerMode mode; // final ValueChanged onModeChanged; // final Orientation orientation; // final bool yearSelectAllowed; // // /// Era custom // final EraMode era; // // /// Border // final double borderRadius; // // /// Header // final ImageProvider imageHeader; // // /// Header description // final String description; // // /// Font // final String fontFamily; // // void _handleChangeMode(DatePickerMode value) { // if (value != mode) onModeChanged(value); // } // // @override // Widget build(BuildContext context) { // final MaterialLocalizations localizations = // MaterialLocalizations.of(context); // final ThemeData themeData = Theme.of(context); // final TextTheme headerTextTheme = themeData.primaryTextTheme; // Color dayColor; // Color yearColor; // switch (themeData.primaryColorBrightness) { // case Brightness.light: // dayColor = mode == DatePickerMode.day ? Colors.black87 : Colors.black54; // yearColor = // mode == DatePickerMode.year ? Colors.black87 : Colors.black54; // break; // case Brightness.dark: // dayColor = mode == DatePickerMode.day ? Colors.white : Colors.white70; // yearColor = mode == DatePickerMode.year ? Colors.white : Colors.white70; // break; // } // final TextStyle dayStyle = headerTextTheme.headline4.copyWith( // color: dayColor, fontFamily: fontFamily, fontWeight: FontWeight.w800); // final TextStyle yearStyle = headerTextTheme.subtitle1.copyWith( // color: yearColor, fontFamily: fontFamily, fontWeight: FontWeight.w800); // // Color backgroundColor; // backgroundColor = themeData.primaryColor; // // EdgeInsets padding; // MainAxisAlignment mainAxisAlignment; // switch (orientation) { // case Orientation.portrait: // padding = const EdgeInsets.all(16.0); // mainAxisAlignment = MainAxisAlignment.center; // break; // case Orientation.landscape: // padding = const EdgeInsets.all(8.0); // mainAxisAlignment = MainAxisAlignment.start; // break; // } // // final Widget yearButton = IgnorePointer( // ignoring: mode != DatePickerMode.day, // ignoringSemantics: false, // child: IgnorePointer( // ignoring: !yearSelectAllowed ?? true, // child: _DateHeaderButton( // color: Colors.transparent, // onTap: Feedback.wrapForTap( // () => _handleChangeMode(DatePickerMode.year), // context, // ), // child: Semantics( // selected: mode == DatePickerMode.year, // child: Text( // "${calculateYearEra(era, selectedDate.year)}", // style: yearStyle, // ), // ), // ), // ), // ); // // final Widget dayButton = IgnorePointer( // ignoring: mode == DatePickerMode.day, // ignoringSemantics: false, // child: _DateHeaderButton( // color: Colors.transparent, // onTap: Feedback.wrapForTap( // () => _handleChangeMode(DatePickerMode.day), // context, // ), // child: Semantics( // selected: mode == DatePickerMode.day, // child: Text( // localizations.formatMediumDate(selectedDate), // style: dayStyle, // ), // ), // ), // ); // // BorderRadius borderRadiusData = BorderRadius.only( // topLeft: Radius.circular(borderRadius), // topRight: Radius.circular(borderRadius), // ); // // if (orientation == Orientation.landscape) { // borderRadiusData = BorderRadius.only( // topLeft: Radius.circular(borderRadius), // bottomLeft: Radius.circular(borderRadius), // ); // } // // return Container( // decoration: BoxDecoration( // image: imageHeader != null // ? DecorationImage(image: imageHeader, fit: BoxFit.cover) // : null, // color: backgroundColor, // borderRadius: borderRadiusData, // ), // padding: padding, // child: Column( // mainAxisAlignment: mainAxisAlignment, // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // yearButton, // dayButton, // const SizedBox(height: 4.0), // Visibility( // visible: description.isNotEmpty, // child: Padding( // padding: EdgeInsets.symmetric(horizontal: 12), // child: Text( // description, // style: TextStyle( // color: yearColor, // fontSize: 12, // fontFamily: fontFamily, // ), // ), // ), // ) // ], // ), // ); // } // } // // class _DateHeaderButton extends StatelessWidget { // const _DateHeaderButton({ // Key key, // this.onTap, // this.color, // this.child, // }) : super(key: key); // // final VoidCallback onTap; // final Color color; // final Widget child; // // @override // Widget build(BuildContext context) { // final ThemeData theme = Theme.of(context); // // return Material( // type: MaterialType.button, // color: color, // child: InkWell( // borderRadius: kMaterialEdges[MaterialType.button], // highlightColor: theme.highlightColor, // splashColor: theme.splashColor, // onTap: onTap, // child: Container( // padding: const EdgeInsets.symmetric(horizontal: 8.0), // child: child, // ), // ), // ); // } // } // // class _DayPickerGridDelegate extends SliverGridDelegate { // const _DayPickerGridDelegate(); // // @override // SliverGridLayout getLayout(SliverConstraints constraints) { // const int columnCount = DateTime.daysPerWeek; // final double tileWidth = constraints.crossAxisExtent / columnCount; // final double viewTileHeight = // constraints.viewportMainAxisExtent / (_kMaxDayPickerRowCount + 1); // final double tileHeight = math.max(_kDayPickerRowHeight, viewTileHeight); // // return SliverGridRegularTileLayout( // crossAxisCount: columnCount, // mainAxisStride: tileHeight, // crossAxisStride: tileWidth, // childMainAxisExtent: tileHeight, // childCrossAxisExtent: tileWidth, // reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection), // ); // } // // @override // bool shouldRelayout(_DayPickerGridDelegate oldDelegate) => false; // } // // const _DayPickerGridDelegate _kDayPickerGridDelegate = _DayPickerGridDelegate(); // // /// Displays the days of a given month and allows choosing a day. // /// // /// The days are arranged in a rectangular grid with one column for each day of // /// the week. // /// // /// The day picker widget is rarely used directly. Instead, consider using // /// [showDatePicker], which creates a date picker dialog. // /// // /// See also: // /// // /// * [showDatePicker], which shows a dialog that contains a material design // /// date picker. // /// * [showTimePicker], which shows a dialog that contains a material design // /// time picker. // class DayPicker extends StatelessWidget { // /// Creates a day picker. // /// // /// Rarely used directly. Instead, typically used as part of a [MonthPicker]. // DayPicker({ // Key key, // @required this.selectedDate, // @required this.currentDate, // @required this.onChanged, // @required this.firstDate, // @required this.lastDate, // @required this.displayedMonth, // this.selectableDayPredicate, // this.dragStartBehavior = DragStartBehavior.start, // this.era, // this.locale, // this.fontFamily, // }) : assert(selectedDate != null), // assert(currentDate != null), // assert(onChanged != null), // assert(displayedMonth != null), // assert(dragStartBehavior != null), // assert(!firstDate.isAfter(lastDate)), // assert(selectedDate.isAfter(firstDate) || // selectedDate.isAtSameMomentAs(firstDate)), // super(key: key); // // /// The currently selected date. // /// // /// This date is highlighted in the picker. // final DateTime selectedDate; // // /// The current date at the time the picker is displayed. // final DateTime currentDate; // // /// Called when the user picks a day. // final ValueChanged onChanged; // // /// The earliest date the user is permitted to pick. // final DateTime firstDate; // // /// The latest date the user is permitted to pick. // final DateTime lastDate; // // /// The month whose days are displayed by this picker. // final DateTime displayedMonth; // // /// Optional user supplied predicate function to customize selectable days. // final SelectableDayPredicate selectableDayPredicate; // // final EraMode era; // final Locale locale; // // final String fontFamily; // // /// Determines the way that drag start behavior is handled. // /// // /// If set to [DragStartBehavior.start], the drag gesture used to scroll a // /// date picker wheel will begin upon the detection of a drag gesture. If set // /// to [DragStartBehavior.down] it will begin when a down event is first // /// detected. // /// // /// In general, setting this to [DragStartBehavior.start] will make drag // /// animation smoother and setting it to [DragStartBehavior.down] will make // /// drag behavior feel slightly more reactive. // /// // /// By default, the drag start behavior is [DragStartBehavior.start]. // /// // /// See also: // /// // /// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors. // final DragStartBehavior dragStartBehavior; // // /// Builds widgets showing abbreviated days of week. The first widget in the // /// returned list corresponds to the first day of week for the current locale. // /// // /// Examples: // /// // /// ``` // /// ┌ Sunday is the first day of week in the US (en_US) // /// | // /// S M T W T F S <-- the returned list contains these widgets // /// _ _ _ _ _ 1 2 // /// 3 4 5 6 7 8 9 // /// // /// ┌ But it's Monday in the UK (en_GB) // /// | // /// M T W T F S S <-- the returned list contains these widgets // /// _ _ _ _ 1 2 3 // /// 4 5 6 7 8 9 10 // /// ``` // List _getDayHeaders( // TextStyle headerStyle, // MaterialLocalizations localizations, // ) { // final List result = []; // for (int i = localizations.firstDayOfWeekIndex; true; i = (i + 1) % 7) { // final String weekday = localizations.narrowWeekdays[i]; // result.add(ExcludeSemantics( // child: Center( // child: Text(weekday, // style: TextStyle( // fontWeight: FontWeight.w800, // fontFamily: "HKGrotesk", // color: Color.fromRGBO(78, 62, 253, 1.0)))), // )); // if (i == (localizations.firstDayOfWeekIndex - 1) % 7) break; // } // // return result; // } // // // Do not use this directly - call getDaysInMonth instead. // static const List _daysInMonth = [ // 31, // -1, // 31, // 30, // 31, // 30, // 31, // 31, // 30, // 31, // 30, // 31, // ]; // // /// Returns the number of days in a month, according to the proleptic // /// Gregorian calendar. // /// // /// This applies the leap year logic introduced by the Gregorian reforms of // /// 1582. It will not give valid results for dates prior to that time. // static int getDaysInMonth(int year, int month) { // if (month == DateTime.february) { // final bool isLeapYear = // (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0); // if (isLeapYear) return 29; // return 28; // } // return _daysInMonth[month - 1]; // } // // /// Computes the offset from the first day of week that the first day of the // /// [month] falls on. // /// // /// For example, September 1, 2017 falls on a Friday, which in the calendar // /// localized for United States English appears as: // /// // /// ``` // /// S M T W T F S // /// _ _ _ _ _ 1 2 // /// ``` // /// // /// The offset for the first day of the months is the number of leading blanks // /// in the calendar, i.e. 5. // /// // /// The same date localized for the Russian calendar has a different offset, // /// because the first day of week is Monday rather than Sunday: // /// // /// ``` // /// M T W T F S S // /// _ _ _ _ 1 2 3 // /// ``` // /// // /// So the offset is 4, rather than 5. // /// // /// This code consolidates the following: // /// // /// - [DateTime.weekday] provides a 1-based index into days of week, with 1 // /// falling on Monday. // /// - [MaterialLocalizations.firstDayOfWeekIndex] provides a 0-based index // /// into the [MaterialLocalizations.narrowWeekdays] list. // /// - [MaterialLocalizations.narrowWeekdays] list provides localized names of // /// days of week, always starting with Sunday and ending with Saturday. // int _computeFirstDayOffset( // int year, int month, MaterialLocalizations localizations) { // // 0-based day of week, with 0 representing Monday. // final int weekdayFromMonday = DateTime(year, month).weekday - 1; // // 0-based day of week, with 0 representing Sunday. // final int firstDayOfWeekFromSunday = localizations.firstDayOfWeekIndex; // // firstDayOfWeekFromSunday recomputed to be Monday-based // final int firstDayOfWeekFromMonday = (firstDayOfWeekFromSunday - 1) % 7; // // Number of days between the first day of week appearing on the calendar, // // and the day corresponding to the 1-st of the month. // return (weekdayFromMonday - firstDayOfWeekFromMonday) % 7; // } // // @override // Widget build(BuildContext context) { // final ThemeData themeData = Theme.of(context); // final MaterialLocalizations localizations = // MaterialLocalizations.of(context); // final int year = displayedMonth.year; // final int month = displayedMonth.month; // final int daysInMonth = getDaysInMonth(year, month); // final int firstDayOffset = _computeFirstDayOffset( // year, // month, // localizations, // ); // // final List labels = _getDayHeaders( // themeData.textTheme.caption.copyWith(color: themeData.primaryColor), // localizations); // for (int i = 0; true; i += 1) { // // 1-based day of month, e.g. 1-31 for January, and 1-29 for February on // // a leap year. // final int day = i - firstDayOffset + 1; // if (day > daysInMonth) break; // if (day < 1) { // labels.add(Container()); // } else { // final DateTime dayToBuild = DateTime(year, month, day); // final bool disabled = dayToBuild.isAfter(lastDate) || // dayToBuild.isBefore(firstDate) || // (selectableDayPredicate != null && // !selectableDayPredicate(dayToBuild)); // // BoxDecoration decoration; // TextStyle itemStyle = themeData.textTheme.bodyText2 // .copyWith(fontFamily: fontFamily, fontWeight: FontWeight.w800); // // final bool isSelectedDay = selectedDate.year == year && // selectedDate.month == month && // selectedDate.day == day; // if (isSelectedDay) { // // The selected day gets a circle background highlight, and a contrasting text color. // itemStyle = themeData.accentTextTheme.bodyText1.copyWith( // fontFamily: fontFamily, // fontWeight: FontWeight.w800, // color: Colors.white); // decoration = BoxDecoration( // color: themeData.primaryColor, // shape: BoxShape.circle, // ); // } else if (disabled) { // itemStyle = themeData.textTheme.bodyText2.copyWith( // color: themeData.disabledColor, // fontFamily: fontFamily, // fontWeight: FontWeight.w800, // ); // } else if (currentDate.year == year && // currentDate.month == month && // currentDate.day == day) { // // The current day gets a different text color. // itemStyle = themeData.textTheme.bodyText1.copyWith( // color: themeData.accentColor, // fontFamily: fontFamily, // fontWeight: FontWeight.w800); // } // // Widget dayWidget = Container( // decoration: decoration, // child: Center( // child: Semantics( // // We want the day of month to be spoken first irrespective of the // // locale-specific preferences or TextDirection. This is because // // an accessibility user is more likely to be interested in the // // day of month before the rest of the date, as they are looking // // for the day of month. To do that we prepend day of month to the // // formatted full date. // label: // '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}', // selected: isSelectedDay, // sortKey: OrdinalSortKey(day.toDouble()), // child: ExcludeSemantics( // child: Text(localizations.formatDecimal(day), style: itemStyle), // ), // ), // ), // ); // // if (!disabled) { // dayWidget = GestureDetector( // behavior: HitTestBehavior.opaque, // onTap: () { // onChanged(dayToBuild); // }, // child: dayWidget, // dragStartBehavior: dragStartBehavior, // ); // } // // labels.add(dayWidget); // } // } // // String monthYearHeader = ""; // monthYearHeader = localizations.formatMonthYear(displayedMonth); // // return Padding( // padding: const EdgeInsets.symmetric(horizontal: 8.0), // child: Column( // children: [ // Container( // height: _kDayPickerRowHeight, // child: Center( // child: ExcludeSemantics( // child: Text( // monthYearHeader, // style: themeData.textTheme.subtitle1.copyWith( // fontFamily: fontFamily, fontWeight: FontWeight.w800), // ), // ), // ), // ), // Flexible( // child: GridView.custom( // gridDelegate: _kDayPickerGridDelegate, // childrenDelegate: SliverChildListDelegate( // labels, // addRepaintBoundaries: false, // ), // padding: EdgeInsets.zero, // ), // ), // ], // ), // ); // } // } // // /// A scrollable list of months to allow picking a month. // /// // /// Shows the days of each month in a rectangular grid with one column for each // /// day of the week. // /// // /// The month picker widget is rarely used directly. Instead, consider using // /// [showDatePicker], which creates a date picker dialog. // /// // /// See also: // /// // /// * [showDatePicker], which shows a dialog that contains a material design // /// date picker. // /// * [showTimePicker], which shows a dialog that contains a material design // /// time picker. // class MonthPicker extends StatefulWidget { // /// Creates a month picker. // /// // /// Rarely used directly. Instead, typically used as part of the dialog shown // /// by [showDatePicker]. // MonthPicker({ // Key key, // @required this.selectedDate, // @required this.onChanged, // @required this.firstDate, // @required this.lastDate, // this.selectableDayPredicate, // this.dragStartBehavior = DragStartBehavior.start, // this.era, // this.locale, // this.fontFamily, // }) : assert(selectedDate != null), // assert(onChanged != null), // assert(!firstDate.isAfter(lastDate)), // assert(selectedDate.isAfter(firstDate) || // selectedDate.isAtSameMomentAs(firstDate)), // super(key: key); // // /// The currently selected date. // /// // /// This date is highlighted in the picker. // final DateTime selectedDate; // // /// Called when the user picks a month. // final ValueChanged onChanged; // // /// The earliest date the user is permitted to pick. // final DateTime firstDate; // // /// The latest date the user is permitted to pick. // final DateTime lastDate; // // /// Optional user supplied predicate function to customize selectable days. // final SelectableDayPredicate selectableDayPredicate; // // /// {@macro flutter.widgets.scrollable.dragStartBehavior} // final DragStartBehavior dragStartBehavior; // // /// Optional era year. // final EraMode era; // final Locale locale; // // /// Font // final String fontFamily; // // @override // _MonthPickerState createState() => _MonthPickerState(); // } // // class _MonthPickerState extends State // with SingleTickerProviderStateMixin { // static final Animatable _chevronOpacityTween = // Tween(begin: 1.0, end: 0.0) // .chain(CurveTween(curve: Curves.easeInOut)); // // @override // void initState() { // super.initState(); // // Initially display the pre-selected date. // final int monthPage = _monthDelta(widget.firstDate, widget.selectedDate); // _dayPickerController = PageController(initialPage: monthPage); // _handleMonthPageChanged(monthPage); // _updateCurrentDate(); // // // Setup the fade animation for chevrons // _chevronOpacityController = AnimationController( // duration: const Duration(milliseconds: 250), // vsync: this, // ); // _chevronOpacityAnimation = _chevronOpacityController.drive( // _chevronOpacityTween, // ); // } // // @override // void didUpdateWidget(MonthPicker oldWidget) { // super.didUpdateWidget(oldWidget); // if (widget.selectedDate != oldWidget.selectedDate) { // final int monthPage = _monthDelta(widget.firstDate, widget.selectedDate); // _dayPickerController = PageController(initialPage: monthPage); // _handleMonthPageChanged(monthPage); // } // } // // MaterialLocalizations localizations; // TextDirection textDirection; // // @override // void didChangeDependencies() { // super.didChangeDependencies(); // localizations = MaterialLocalizations.of(context); // textDirection = Directionality.of(context); // } // // DateTime _todayDate; // DateTime _currentDisplayedMonthDate; // Timer _timer; // PageController _dayPickerController; // AnimationController _chevronOpacityController; // Animation _chevronOpacityAnimation; // // void _updateCurrentDate() { // _todayDate = DateTime.now(); // final DateTime tomorrow = // DateTime(_todayDate.year, _todayDate.month, _todayDate.day + 1); // Duration timeUntilTomorrow = tomorrow.difference(_todayDate); // // so we don't miss it by rounding // timeUntilTomorrow += const Duration(seconds: 1); // _timer?.cancel(); // _timer = Timer(timeUntilTomorrow, () { // setState(() => _updateCurrentDate()); // }); // } // // static int _monthDelta(DateTime startDate, DateTime endDate) { // return (endDate.year - startDate.year) * 12 + // endDate.month - // startDate.month; // } // // /// Add months to a month truncated date. // DateTime _addMonthsToMonthDate(DateTime monthDate, int monthsToAdd) { // return DateTime( // monthDate.year + monthsToAdd ~/ 12, // monthDate.month + monthsToAdd % 12, // ); // } // // Widget _buildItems(BuildContext context, int index) { // final DateTime month = _addMonthsToMonthDate(widget.firstDate, index); // return DayPicker( // key: ValueKey(month), // selectedDate: widget.selectedDate, // currentDate: _todayDate, // onChanged: widget.onChanged, // firstDate: widget.firstDate, // lastDate: widget.lastDate, // displayedMonth: month, // selectableDayPredicate: widget.selectableDayPredicate, // dragStartBehavior: widget.dragStartBehavior, // era: widget.era, // locale: widget.locale, // fontFamily: widget.fontFamily, // ); // } // // void _handleNextMonth() { // if (!_isDisplayingLastMonth) { // SemanticsService.announce( // localizations.formatMonthYear(_nextMonthDate), // textDirection, // ); // _dayPickerController.nextPage( // duration: _kMonthScrollDuration, // curve: Curves.ease, // ); // } // } // // void _handlePreviousMonth() { // if (!_isDisplayingFirstMonth) { // SemanticsService.announce( // localizations.formatMonthYear(_previousMonthDate), // textDirection, // ); // _dayPickerController.previousPage( // duration: _kMonthScrollDuration, // curve: Curves.ease, // ); // } // } // // /// True if the earliest allowable month is displayed. // bool get _isDisplayingFirstMonth { // return !_currentDisplayedMonthDate.isAfter( // DateTime(widget.firstDate.year, widget.firstDate.month), // ); // } // // /// True if the latest allowable month is displayed. // bool get _isDisplayingLastMonth { // return !_currentDisplayedMonthDate.isBefore( // DateTime(widget.lastDate.year, widget.lastDate.month), // ); // } // // DateTime _previousMonthDate; // DateTime _nextMonthDate; // // void _handleMonthPageChanged(int monthPage) { // setState(() { // _previousMonthDate = _addMonthsToMonthDate( // widget.firstDate, // monthPage - 1, // ); // _currentDisplayedMonthDate = _addMonthsToMonthDate( // widget.firstDate, // monthPage, // ); // _nextMonthDate = _addMonthsToMonthDate(widget.firstDate, monthPage + 1); // }); // } // // @override // Widget build(BuildContext context) { // return SizedBox( // // The month picker just adds month navigation to the day picker, so make // // it the same height as the DayPicker // height: _kMaxDayPickerHeight, // child: Stack( // children: [ // Semantics( // sortKey: _MonthPickerSortKey.calendar, // child: NotificationListener( // onNotification: (_) { // _chevronOpacityController.forward(); // return false; // }, // child: NotificationListener( // onNotification: (_) { // _chevronOpacityController.reverse(); // return false; // }, // child: PageView.builder( // physics: BouncingScrollPhysics(), // dragStartBehavior: widget.dragStartBehavior, // key: ValueKey(widget.selectedDate), // controller: _dayPickerController, // scrollDirection: Axis.horizontal, // itemCount: _monthDelta(widget.firstDate, widget.lastDate) + 1, // itemBuilder: _buildItems, // onPageChanged: _handleMonthPageChanged, // ), // ), // ), // ), // // /// Arrow Left // PositionedDirectional( // top: 0.0, // start: 8.0, // child: Semantics( // sortKey: _MonthPickerSortKey.previousMonth, // child: FadeTransition( // opacity: _chevronOpacityAnimation, // child: IconButton( // disabledColor: // Theme.of(context).disabledColor.withOpacity(0.2), // color: Theme.of(context).disabledColor, // icon: const Icon(Icons.chevron_left_sharp), // tooltip: _isDisplayingFirstMonth // ? null // : '${localizations.previousMonthTooltip} ${localizations.formatMonthYear(_previousMonthDate)}', // onPressed: _isDisplayingFirstMonth == true // ? null // : _handlePreviousMonth, // ), // ), // ), // ), // // /// Arrow Right // PositionedDirectional( // top: 0.0, // end: 8.0, // child: Semantics( // sortKey: _MonthPickerSortKey.nextMonth, // child: FadeTransition( // opacity: _chevronOpacityAnimation, // child: IconButton( // disabledColor: // Theme.of(context).disabledColor.withOpacity(0.2), // color: Theme.of(context).disabledColor, // icon: const Icon(Icons.chevron_right_sharp), // tooltip: _isDisplayingLastMonth // ? null // : '${localizations.nextMonthTooltip} ${localizations.formatMonthYear(_nextMonthDate)}', // onPressed: _isDisplayingLastMonth ? null : _handleNextMonth, // ), // ), // ), // ), // ], // ), // ); // } // // @override // void dispose() { // _timer?.cancel(); // _chevronOpacityController?.dispose(); // _dayPickerController?.dispose(); // super.dispose(); // } // } // // // Defines semantic traversal order of the top-level widgets inside the month // // picker. // class _MonthPickerSortKey extends OrdinalSortKey { // const _MonthPickerSortKey(double order) : super(order); // // static const _MonthPickerSortKey previousMonth = _MonthPickerSortKey(1.0); // static const _MonthPickerSortKey nextMonth = _MonthPickerSortKey(2.0); // static const _MonthPickerSortKey calendar = _MonthPickerSortKey(3.0); // } // // /// A scrollable list of years to allow picking a year. // /// // /// The year picker widget is rarely used directly. Instead, consider using // /// [showDatePicker], which creates a date picker dialog. // /// // /// Requires one of its ancestors to be a [Material] widget. // /// // /// See also: // /// // /// * [showDatePicker], which shows a dialog that contains a material design // /// date picker. // /// * [showTimePicker], which shows a dialog that contains a material design // /// time picker. // class YearPicker extends StatefulWidget { // /// Creates a year picker. // /// // /// The [selectedDate] and [onChanged] arguments must not be null. The // /// [lastDate] must be after the [firstDate]. // /// // /// Rarely used directly. Instead, typically used as part of the dialog shown // /// by [showDatePicker]. // YearPicker({ // Key key, // @required this.selectedDate, // @required this.onChanged, // @required this.firstDate, // @required this.lastDate, // this.era = EraMode.CHRIST_YEAR, // this.fontFamily, // this.dragStartBehavior = DragStartBehavior.start, // }) : assert(selectedDate != null), // assert(onChanged != null), // assert(!firstDate.isAfter(lastDate)), // super(key: key); // // /// The currently selected date. // /// // /// This date is highlighted in the picker. // final DateTime selectedDate; // // /// Called when the user picks a year. // final ValueChanged onChanged; // // /// The earliest date the user is permitted to pick. // final DateTime firstDate; // // /// The latest date the user is permitted to pick. // final DateTime lastDate; // // /// {@macro flutter.widgets.scrollable.dragStartBehavior} // final DragStartBehavior dragStartBehavior; // // /// Era // final EraMode era; // // /// Font // final String fontFamily; // // @override // _YearPickerState createState() => _YearPickerState(); // } // // class _YearPickerState extends State { // static const double _itemExtent = 50.0; // ScrollController scrollController; // // @override // void initState() { // super.initState(); // scrollController = ScrollController( // // Move the initial scroll position to the currently selected date's year. // initialScrollOffset: // (widget.selectedDate.year - widget.firstDate.year) * _itemExtent, // ); // } // // @override // Widget build(BuildContext context) { // assert(debugCheckHasMaterial(context)); // final ThemeData themeData = Theme.of(context); // final TextStyle style = themeData.textTheme.bodyText2 // .copyWith(fontFamily: widget.fontFamily, fontWeight: FontWeight.w700); // return ConstrainedBox( // constraints: BoxConstraints(maxHeight: 300), // child: ListView.builder( // physics: BouncingScrollPhysics(), // dragStartBehavior: widget.dragStartBehavior, // controller: scrollController, // itemExtent: _itemExtent, // itemCount: widget.lastDate.year - widget.firstDate.year + 1, // itemBuilder: (BuildContext context, int index) { // final int year = widget.firstDate.year + index; // final bool isSelected = year == widget.selectedDate.year; // final TextStyle itemStyle = isSelected // ? themeData.textTheme.headline5.copyWith( // color: themeData.accentColor, // fontFamily: widget.fontFamily, // fontWeight: FontWeight.w900) // : style; // return InkWell( // key: ValueKey(year), // onTap: () { // widget.onChanged(DateTime( // year, // widget.selectedDate.month, // widget.selectedDate.day, // )); // }, // child: Center( // child: Semantics( // selected: isSelected, // child: Text( // "${calculateYearEra(widget.era, year)}", // style: itemStyle, // ), // ), // ), // ); // }, // ), // ); // } // } // // class DatePickerDialog extends StatefulWidget { // const DatePickerDialog({ // Key key, // this.initialDate, // this.yearSelectAllowed, // this.firstDate, // this.lastDate, // this.selectableDayPredicate, // this.initialDatePickerMode, // this.era, // this.locale, // this.borderRadius, // this.imageHeader, // this.description = "", // this.fontFamily, // this.negativeBtn, // this.positiveBtn, // this.leftBtn, // this.onLeftBtn, // }) : super(key: key); // // final DateTime initialDate; // final DateTime firstDate; // final DateTime lastDate; // final SelectableDayPredicate selectableDayPredicate; // final DatePickerMode initialDatePickerMode; // final bool yearSelectAllowed; // // /// Custom era year. // final EraMode era; // final Locale locale; // // /// Border // final double borderRadius; // // /// Header; // final ImageProvider imageHeader; // final String description; // // /// Font // final String fontFamily; // // final String negativeBtn; // final String positiveBtn; // final String leftBtn; // final VoidCallback onLeftBtn; // // @override // _DatePickerDialogState createState() => _DatePickerDialogState(); // } // // class _DatePickerDialogState extends State { // @override // void initState() { // super.initState(); // _selectedDate = widget.initialDate; // _mode = widget.initialDatePickerMode; // } // // bool _announcedInitialDate = false; // // MaterialLocalizations localizations; // TextDirection textDirection; // // @override // void didChangeDependencies() { // super.didChangeDependencies(); // localizations = MaterialLocalizations.of(context); // textDirection = Directionality.of(context); // if (!_announcedInitialDate) { // _announcedInitialDate = true; // SemanticsService.announce( // localizations.formatFullDate(_selectedDate), // textDirection, // ); // } // } // // DateTime _selectedDate; // DatePickerMode _mode; // final GlobalKey _pickerKey = GlobalKey(); // // void _vibrate() { // HapticFeedback.vibrate(); // } // // void _handleModeChanged(DatePickerMode mode) { // _vibrate(); // setState(() { // _mode = mode; // if (_mode == DatePickerMode.day) { // SemanticsService.announce( // localizations.formatMonthYear(_selectedDate), // textDirection, // ); // } else { // SemanticsService.announce( // localizations.formatYear(_selectedDate), // textDirection, // ); // } // }); // } // // void _handleYearChanged(DateTime value) { // if (value.isBefore(widget.firstDate)) { // value = widget.firstDate; // } else if (value.isAfter(widget.lastDate)) { // value = widget.lastDate; // } // if (value == _selectedDate) return; // // _vibrate(); // setState(() { // _mode = DatePickerMode.day; // _selectedDate = value; // }); // } // // void _handleDayChanged(DateTime value) { // _vibrate(); // setState(() { // _selectedDate = value; // }); // } // // void _handleOk() { // Navigator.of(context).pop(_selectedDate); // } // // Widget _buildPicker() { // assert(_mode != null); // switch (_mode) { // case DatePickerMode.day: // return MonthPicker( // key: _pickerKey, // selectedDate: _selectedDate, // onChanged: _handleDayChanged, // firstDate: widget.firstDate, // lastDate: widget.lastDate, // era: widget.era, // locale: widget.locale, // selectableDayPredicate: widget.selectableDayPredicate, // fontFamily: widget.fontFamily, // ); // case DatePickerMode.year: // return YearPicker( // key: _pickerKey, // selectedDate: _selectedDate, // onChanged: _handleYearChanged, // firstDate: widget.firstDate, // lastDate: widget.lastDate, // era: widget.era, // fontFamily: widget.fontFamily, // ); // } // return null; // } // // @override // Widget build(BuildContext context) { // final ThemeData theme = Theme.of(context); // final Widget picker = _buildPicker(); // // final Widget actions = ButtonActions(onPositive: _handleOk); // // final Dialog dialog = Dialog( // child: OrientationBuilder( // builder: (BuildContext context, Orientation orientation) { // assert(orientation != null); // final Widget header = _DatePickerHeader( // selectedDate: _selectedDate, // yearSelectAllowed: widget.yearSelectAllowed ?? true, // mode: _mode, // onModeChanged: _handleModeChanged, // orientation: orientation, // era: widget.era, // borderRadius: widget.borderRadius, // imageHeader: widget.imageHeader, // description: widget.description, // fontFamily: widget.fontFamily, // ); // switch (orientation) { // case Orientation.portrait: // return Container( // decoration: BoxDecoration( // color: theme.dialogBackgroundColor, // borderRadius: BorderRadius.circular(widget.borderRadius), // ), // child: Column( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.stretch, // children: [ // header, // Flexible(child: picker), // actions, // ], // ), // ); // case Orientation.landscape: // return Container( // decoration: BoxDecoration( // color: theme.dialogBackgroundColor, // borderRadius: BorderRadius.circular(widget.borderRadius), // ), // child: Row( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.stretch, // children: [ // Flexible(child: header), // Flexible( // flex: 2, // // have the picker take up 2/3 of the dialog width // child: Column( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.stretch, // children: [ // Flexible(child: picker), // actions, // ], // ), // ), // ], // ), // ); // } // return null; // }), // ); // // return Theme( // data: theme.copyWith(dialogBackgroundColor: Colors.transparent), // child: dialog, // ); // } // } // // /// Signature for predicating dates for enabled date selections. // /// // /// See [showDatePicker]. // typedef SelectableDayPredicate = bool Function(DateTime day); // // /// Shows a dialog containing a material design date picker. // /// // /// The returned [Future] resolves to the date selected by the user when the // /// user closes the dialog. If the user cancels the dialog, null is returned. // /// // /// An optional [selectableDayPredicate] function can be passed in to customize // /// the days to enable for selection. If provided, only the days that // /// [selectableDayPredicate] returned true for will be selectable. // /// // /// An optional [initialDatePickerMode] argument can be used to display the // /// date picker initially in the year or month+day picker mode. It defaults // /// to month+day, and must not be null. // /// // /// An optional [locale] argument can be used to set the locale for the date // /// picker. It defaults to the ambient locale provided by [Localizations]. // /// // /// An optional [textDirection] argument can be used to set the text direction // /// (RTL or LTR) for the date picker. It defaults to the ambient text direction // /// provided by [Directionality]. If both [locale] and [textDirection] are not // /// null, [textDirection] overrides the direction chosen for the [locale]. // /// // /// The [context] argument is passed to [showDialog], the documentation for // /// which discusses how it is used. // /// // /// The [builder] parameter can be used to wrap the dialog widget // /// to add inherited widgets like [Theme]. // /// // /// {@tool sample} // /// Show a date picker with the dark theme. // /// // /// ```dart // /// Future selectedDate = showDatePicker( // /// context: context, // /// initialDate: DateTime.now(), // /// firstDate: DateTime(2018), // /// lastDate: DateTime(2030), // /// builder: (BuildContext context, Widget child) { // /// return Theme( // /// data: ThemeData.dark(), // /// child: child, // /// ); // /// }, // /// ); // /// ``` // /// {@end-tool} // /// // /// The [context], [initialDate], [firstDate], and [lastDate] parameters must // /// not be null. // /// // /// See also: // /// // /// * [showTimePicker], which shows a dialog that contains a material design // /// time picker. // /// * [DayPicker], which displays the days of a given month and allows // /// choosing a day. // /// * [MonthPicker], which displays a scrollable list of months to allow // /// picking a month. // /// * [YearPicker], which displays a scrollable list of years to allow picking // /// a year. // /// // // Future showRoundedDatePicker( // {@required BuildContext context, // DateTime initialDate, // DateTime firstDate, // DateTime lastDate, // SelectableDayPredicate selectableDayPredicate, // DatePickerMode initialDatePickerMode = DatePickerMode.day, // Locale locale, // TextDirection textDirection, // ThemeData theme, // double borderRadius = 16, // EraMode era = EraMode.CHRIST_YEAR, // ImageProvider imageHeader, // String description = "", // String fontFamily, // bool barrierDismissible = false, // Color background = Colors.transparent, // String negativeBtn, // String positiveBtn, // String leftBtn, // VoidCallback onLeftBtn, // bool yearSelectAllowed}) async { // initialDate ??= DateTime.now(); // firstDate ??= DateTime(initialDate.year - 1); // lastDate ??= DateTime(initialDate.year + 1); // theme ??= ThemeData(); // // assert(initialDate != null); // assert(firstDate != null); // assert(lastDate != null); // assert( // !initialDate.isBefore(firstDate), // 'initialDate must be on or after firstDate', // ); // assert( // !initialDate.isAfter(lastDate), // 'initialDate must be on or before lastDate', // ); // assert( // !firstDate.isAfter(lastDate), // 'lastDate must be on or after firstDate', // ); // assert( // selectableDayPredicate == null || selectableDayPredicate(initialDate), // 'Provided initialDate must satisfy provided selectableDayPredicate', // ); // assert( // initialDatePickerMode != null, // 'initialDatePickerMode must not be null', // ); // assert( // (onLeftBtn != null && leftBtn != null) || onLeftBtn == null, // "If you provide onLeftBtn, you must provide leftBtn", // ); // assert(context != null); // assert(debugCheckHasMaterialLocalizations(context)); // // Widget child = GestureDetector( // onTap: () { // if (!barrierDismissible) { // Navigator.pop(context); // } // }, // child: Container( // color: background, // child: GestureDetector( // onTap: () { // // // }, // child: DatePickerDialog( // initialDate: initialDate, // firstDate: firstDate, // lastDate: lastDate, // yearSelectAllowed: yearSelectAllowed, // selectableDayPredicate: selectableDayPredicate, // initialDatePickerMode: initialDatePickerMode, // era: era, // locale: locale, // borderRadius: borderRadius, // imageHeader: imageHeader, // description: description, // fontFamily: fontFamily, // negativeBtn: negativeBtn, // positiveBtn: positiveBtn, // leftBtn: leftBtn, // onLeftBtn: onLeftBtn, // ), // ), // ), // ); // // if (textDirection != null) { // child = Directionality( // textDirection: textDirection, // child: child, // ); // } // // if (locale != null) { // child = Localizations.override( // context: context, // locale: locale, // child: child, // ); // } // // return await showDialog( // context: context, // barrierDismissible: barrierDismissible, // builder: (_) => Theme(data: theme, child: child), // ); // }