Chevrons in month picker are semi-transparent when the month is scrolled (#19363)
* Chevrons in month picker are semi-transparent when the month is scrolled * Added type missing annotation
This commit is contained in:
parent
6a8f904104
commit
d10e46ea65
@ -524,7 +524,7 @@ class MonthPicker extends StatefulWidget {
|
||||
_MonthPickerState createState() => new _MonthPickerState();
|
||||
}
|
||||
|
||||
class _MonthPickerState extends State<MonthPicker> {
|
||||
class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStateMixin {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@ -533,6 +533,17 @@ class _MonthPickerState extends State<MonthPicker> {
|
||||
_dayPickerController = new PageController(initialPage: monthPage);
|
||||
_handleMonthPageChanged(monthPage);
|
||||
_updateCurrentDate();
|
||||
|
||||
// Setup the fade animation for chevrons
|
||||
_chevronOpacityController = new AnimationController(
|
||||
duration: const Duration(milliseconds: 500), vsync: this
|
||||
);
|
||||
_chevronOpacityAnimation = new Tween<double>(begin: 1.0, end: 0.5).animate(
|
||||
new CurvedAnimation(
|
||||
parent: _chevronOpacityController,
|
||||
curve: Curves.easeInOut,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -559,6 +570,8 @@ class _MonthPickerState extends State<MonthPicker> {
|
||||
DateTime _currentDisplayedMonthDate;
|
||||
Timer _timer;
|
||||
PageController _dayPickerController;
|
||||
AnimationController _chevronOpacityController;
|
||||
Animation<double> _chevronOpacityAnimation;
|
||||
|
||||
void _updateCurrentDate() {
|
||||
_todayDate = new DateTime.now();
|
||||
@ -642,13 +655,25 @@ class _MonthPickerState extends State<MonthPicker> {
|
||||
children: <Widget>[
|
||||
new Semantics(
|
||||
sortKey: _MonthPickerSortKey.calendar,
|
||||
child: new PageView.builder(
|
||||
key: new ValueKey<DateTime>(widget.selectedDate),
|
||||
controller: _dayPickerController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _monthDelta(widget.firstDate, widget.lastDate) + 1,
|
||||
itemBuilder: _buildItems,
|
||||
onPageChanged: _handleMonthPageChanged,
|
||||
child: new NotificationListener<ScrollStartNotification>(
|
||||
onNotification: (_) {
|
||||
_chevronOpacityController.forward();
|
||||
return false;
|
||||
},
|
||||
child: new NotificationListener<ScrollEndNotification>(
|
||||
onNotification: (_) {
|
||||
_chevronOpacityController.reverse();
|
||||
return false;
|
||||
},
|
||||
child: new PageView.builder(
|
||||
key: new ValueKey<DateTime>(widget.selectedDate),
|
||||
controller: _dayPickerController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _monthDelta(widget.firstDate, widget.lastDate) + 1,
|
||||
itemBuilder: _buildItems,
|
||||
onPageChanged: _handleMonthPageChanged,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
new PositionedDirectional(
|
||||
@ -656,10 +681,13 @@ class _MonthPickerState extends State<MonthPicker> {
|
||||
start: 8.0,
|
||||
child: new Semantics(
|
||||
sortKey: _MonthPickerSortKey.previousMonth,
|
||||
child: new IconButton(
|
||||
icon: const Icon(Icons.chevron_left),
|
||||
tooltip: _isDisplayingFirstMonth ? null : '${localizations.previousMonthTooltip} ${localizations.formatMonthYear(_previousMonthDate)}',
|
||||
onPressed: _isDisplayingFirstMonth ? null : _handlePreviousMonth,
|
||||
child: new FadeTransition(
|
||||
opacity: _chevronOpacityAnimation,
|
||||
child: new IconButton(
|
||||
icon: const Icon(Icons.chevron_left),
|
||||
tooltip: _isDisplayingFirstMonth ? null : '${localizations.previousMonthTooltip} ${localizations.formatMonthYear(_previousMonthDate)}',
|
||||
onPressed: _isDisplayingFirstMonth ? null : _handlePreviousMonth,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -668,10 +696,13 @@ class _MonthPickerState extends State<MonthPicker> {
|
||||
end: 8.0,
|
||||
child: new Semantics(
|
||||
sortKey: _MonthPickerSortKey.nextMonth,
|
||||
child: new IconButton(
|
||||
icon: const Icon(Icons.chevron_right),
|
||||
tooltip: _isDisplayingLastMonth ? null : '${localizations.nextMonthTooltip} ${localizations.formatMonthYear(_nextMonthDate)}',
|
||||
onPressed: _isDisplayingLastMonth ? null : _handleNextMonth,
|
||||
child: new FadeTransition(
|
||||
opacity: _chevronOpacityAnimation,
|
||||
child: new IconButton(
|
||||
icon: const Icon(Icons.chevron_right),
|
||||
tooltip: _isDisplayingLastMonth ? null : '${localizations.nextMonthTooltip} ${localizations.formatMonthYear(_nextMonthDate)}',
|
||||
onPressed: _isDisplayingLastMonth ? null : _handleNextMonth,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -622,4 +622,65 @@ void _tests() {
|
||||
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('chervons animate when scrolling month picker', (WidgetTester tester) async {
|
||||
final Key _datePickerKey = new UniqueKey();
|
||||
DateTime _selectedDate = new DateTime(2016, DateTime.july, 26);
|
||||
|
||||
await tester.pumpWidget(
|
||||
new MaterialApp(
|
||||
home: new StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return new Container(
|
||||
width: 400.0,
|
||||
child: new SingleChildScrollView(
|
||||
child: new Material(
|
||||
child: new MonthPicker(
|
||||
firstDate: new DateTime(0),
|
||||
lastDate: new DateTime(9999),
|
||||
key: _datePickerKey,
|
||||
selectedDate: _selectedDate,
|
||||
onChanged: (DateTime value) {
|
||||
setState(() {
|
||||
_selectedDate = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
final Finder chevronFinder = find.byType(IconButton);
|
||||
final List<RenderAnimatedOpacity> chevronRenderers = chevronFinder.evaluate().map(
|
||||
(Element element) => element.ancestorRenderObjectOfType(
|
||||
const TypeMatcher<RenderAnimatedOpacity>())).cast<RenderAnimatedOpacity>().toList();
|
||||
|
||||
// Initial chevron animation state should be dismissed
|
||||
// An AlwaysStoppedAnimation is also found and is ignored
|
||||
for(RenderAnimatedOpacity renderer in chevronRenderers) {
|
||||
expect(renderer.opacity.value, equals(1.0));
|
||||
expect(renderer.opacity.status, equals(AnimationStatus.dismissed));
|
||||
}
|
||||
|
||||
// Drag and hold the picker to test for the opacity change
|
||||
final TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
|
||||
await gesture.moveBy(const Offset(50.0, 100.0));
|
||||
await tester.pumpAndSettle();
|
||||
for(RenderAnimatedOpacity renderer in chevronRenderers) {
|
||||
expect(renderer.opacity.value, equals(0.5));
|
||||
expect(renderer.opacity.status, equals(AnimationStatus.completed));
|
||||
}
|
||||
|
||||
// Release the drag and test for the opacity to return to original value
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
for(RenderAnimatedOpacity renderer in chevronRenderers) {
|
||||
expect(renderer.opacity.value, equals(1.0));
|
||||
expect(renderer.opacity.status, equals(AnimationStatus.dismissed));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user