Unverified Commit 8737472a authored by Darren Austin's avatar Darren Austin Committed by GitHub

Exposed the YearPicker as a public API again to match the previous API. (#71061)

parent accedc67
......@@ -278,7 +278,7 @@ class _CalendarDatePickerState extends State<CalendarDatePicker> {
case DatePickerMode.year:
return Padding(
padding: const EdgeInsets.only(top: _subHeaderHeight),
child: _YearPicker(
child: YearPicker(
key: _yearPickerKey,
currentDate: widget.currentDate,
firstDate: widget.firstDate,
......@@ -1095,12 +1095,12 @@ const _DayPickerGridDelegate _dayPickerGridDelegate = _DayPickerGridDelegate();
/// * [showDatePicker], which shows a dialog containing a Material Design
/// date picker.
///
class _YearPicker extends StatefulWidget {
class YearPicker extends StatefulWidget {
/// Creates a year picker.
///
/// The [firstDate], [lastDate], [selectedDate], and [onChanged]
/// arguments must be non-null. The [lastDate] must be after the [firstDate].
_YearPicker({
YearPicker({
Key? key,
DateTime? currentDate,
required this.firstDate,
......@@ -1147,7 +1147,7 @@ class _YearPicker extends StatefulWidget {
_YearPickerState createState() => _YearPickerState();
}
class _YearPickerState extends State<_YearPicker> {
class _YearPickerState extends State<YearPicker> {
late ScrollController _scrollController;
// The approximate number of years necessary to fill the available space.
......@@ -1160,7 +1160,7 @@ class _YearPickerState extends State<_YearPicker> {
}
@override
void didUpdateWidget(_YearPicker oldWidget) {
void didUpdateWidget(YearPicker oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.selectedDate != oldWidget.selectedDate) {
_scrollController.jumpTo(_scrollOffsetForYear(widget.selectedDate));
......
......@@ -10,11 +10,8 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'date.dart';
import 'debug.dart';
import 'icon_button.dart';
import 'icons.dart';
import 'ink_well.dart';
import 'material.dart';
import 'material_localizations.dart';
import 'theme.dart';
......@@ -609,108 +606,3 @@ class _MonthPickerSortKey extends OrdinalSortKey {
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.
///
@Deprecated(
'Use CalendarDatePicker instead. '
'This feature was deprecated after v1.15.3.'
)
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.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<DateTime> 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;
@override
_YearPickerState createState() => _YearPickerState();
}
class _YearPickerState extends State<YearPicker> {
static const double _itemExtent = 50.0;
late 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;
return ListView.builder(
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)
: style;
return InkWell(
key: ValueKey<int>(year),
onTap: () {
widget.onChanged(DateTime(year, widget.selectedDate.month, widget.selectedDate.day));
},
child: Center(
child: Semantics(
selected: isSelected,
child: Text(year.toString(), style: itemStyle),
),
),
);
},
);
}
}
......@@ -47,6 +47,34 @@ void main() {
);
}
Widget yearPicker({
Key? key,
DateTime? selectedDate,
DateTime? initialDate,
DateTime? firstDate,
DateTime? lastDate,
DateTime? currentDate,
ValueChanged<DateTime>? onChanged,
TextDirection textDirection = TextDirection.ltr,
}) {
return MaterialApp(
home: Material(
child: Directionality(
textDirection: textDirection,
child: YearPicker(
key: key,
selectedDate: selectedDate ?? DateTime(2016, DateTime.january, 15),
initialDate: initialDate ?? DateTime(2016, DateTime.january, 15),
firstDate: firstDate ?? DateTime(2001, DateTime.january, 1),
lastDate: lastDate ?? DateTime(2031, DateTime.december, 31),
currentDate: currentDate ?? DateTime(2016, DateTime.january, 3),
onChanged: onChanged ?? (DateTime date) {},
),
),
),
);
}
group('CalendarDatePicker', () {
testWidgets('Can select a day', (WidgetTester tester) async {
DateTime? selectedDate;
......@@ -163,13 +191,6 @@ void main() {
expect(selectedDate, equals(DateTime(2017, DateTime.january, 19)));
});
testWidgets('Current year is visible in year picker', (WidgetTester tester) async {
await tester.pumpWidget(calendarDatePicker());
await tester.tap(find.text('January 2016')); // Switch to year mode.
await tester.pumpAndSettle();
expect(find.text('2016'), findsOneWidget);
});
testWidgets('Cannot select a day outside bounds', (WidgetTester tester) async {
final DateTime validDate = DateTime(2017, DateTime.january, 15);
DateTime? selectedDate;
......@@ -193,8 +214,7 @@ void main() {
expect(selectedDate, validDate);
});
testWidgets('Cannot navigate to a month outside bounds', (
WidgetTester tester) async {
testWidgets('Cannot navigate to a month outside bounds', (WidgetTester tester) async {
DateTime? displayedMonth;
await tester.pumpWidget(calendarDatePicker(
firstDate: DateTime(2016, DateTime.december, 15),
......@@ -832,4 +852,41 @@ void main() {
});
});
group('YearPicker', () {
testWidgets('Current year is visible in year picker', (WidgetTester tester) async {
await tester.pumpWidget(yearPicker());
expect(find.text('2016'), findsOneWidget);
});
testWidgets('Can select a year', (WidgetTester tester) async {
DateTime? selectedDate;
await tester.pumpWidget(yearPicker(
onChanged: (DateTime date) => selectedDate = date,
));
await tester.pumpAndSettle();
await tester.tap(find.text('2018'));
await tester.pumpAndSettle();
expect(selectedDate, equals(DateTime(2018, DateTime.january, 1)));
});
testWidgets('Cannot select disabled year', (WidgetTester tester) async {
DateTime? selectedYear;
await tester.pumpWidget(yearPicker(
firstDate: DateTime(2018, DateTime.june, 9),
initialDate: DateTime(2018, DateTime.july, 4),
lastDate: DateTime(2018, DateTime.december, 15),
onChanged: (DateTime date) => selectedYear = date,
));
await tester.tap(find.text('2016')); // Disabled, doesn't change the year.
await tester.pumpAndSettle();
expect(selectedYear, isNull);
await tester.tap(find.text('2020')); // Disabled, doesn't change the year.
await tester.pumpAndSettle();
expect(selectedYear, isNull);
await tester.tap(find.text('2018'));
await tester.pumpAndSettle();
expect(selectedYear, equals(DateTime(2018, DateTime.july, 1)));
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment