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();
|
_MonthPickerState createState() => new _MonthPickerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MonthPickerState extends State<MonthPicker> {
|
class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStateMixin {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -533,6 +533,17 @@ class _MonthPickerState extends State<MonthPicker> {
|
|||||||
_dayPickerController = new PageController(initialPage: monthPage);
|
_dayPickerController = new PageController(initialPage: monthPage);
|
||||||
_handleMonthPageChanged(monthPage);
|
_handleMonthPageChanged(monthPage);
|
||||||
_updateCurrentDate();
|
_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
|
@override
|
||||||
@ -559,6 +570,8 @@ class _MonthPickerState extends State<MonthPicker> {
|
|||||||
DateTime _currentDisplayedMonthDate;
|
DateTime _currentDisplayedMonthDate;
|
||||||
Timer _timer;
|
Timer _timer;
|
||||||
PageController _dayPickerController;
|
PageController _dayPickerController;
|
||||||
|
AnimationController _chevronOpacityController;
|
||||||
|
Animation<double> _chevronOpacityAnimation;
|
||||||
|
|
||||||
void _updateCurrentDate() {
|
void _updateCurrentDate() {
|
||||||
_todayDate = new DateTime.now();
|
_todayDate = new DateTime.now();
|
||||||
@ -642,13 +655,25 @@ class _MonthPickerState extends State<MonthPicker> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new Semantics(
|
new Semantics(
|
||||||
sortKey: _MonthPickerSortKey.calendar,
|
sortKey: _MonthPickerSortKey.calendar,
|
||||||
child: new PageView.builder(
|
child: new NotificationListener<ScrollStartNotification>(
|
||||||
key: new ValueKey<DateTime>(widget.selectedDate),
|
onNotification: (_) {
|
||||||
controller: _dayPickerController,
|
_chevronOpacityController.forward();
|
||||||
scrollDirection: Axis.horizontal,
|
return false;
|
||||||
itemCount: _monthDelta(widget.firstDate, widget.lastDate) + 1,
|
},
|
||||||
itemBuilder: _buildItems,
|
child: new NotificationListener<ScrollEndNotification>(
|
||||||
onPageChanged: _handleMonthPageChanged,
|
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(
|
new PositionedDirectional(
|
||||||
@ -656,10 +681,13 @@ class _MonthPickerState extends State<MonthPicker> {
|
|||||||
start: 8.0,
|
start: 8.0,
|
||||||
child: new Semantics(
|
child: new Semantics(
|
||||||
sortKey: _MonthPickerSortKey.previousMonth,
|
sortKey: _MonthPickerSortKey.previousMonth,
|
||||||
child: new IconButton(
|
child: new FadeTransition(
|
||||||
icon: const Icon(Icons.chevron_left),
|
opacity: _chevronOpacityAnimation,
|
||||||
tooltip: _isDisplayingFirstMonth ? null : '${localizations.previousMonthTooltip} ${localizations.formatMonthYear(_previousMonthDate)}',
|
child: new IconButton(
|
||||||
onPressed: _isDisplayingFirstMonth ? null : _handlePreviousMonth,
|
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,
|
end: 8.0,
|
||||||
child: new Semantics(
|
child: new Semantics(
|
||||||
sortKey: _MonthPickerSortKey.nextMonth,
|
sortKey: _MonthPickerSortKey.nextMonth,
|
||||||
child: new IconButton(
|
child: new FadeTransition(
|
||||||
icon: const Icon(Icons.chevron_right),
|
opacity: _chevronOpacityAnimation,
|
||||||
tooltip: _isDisplayingLastMonth ? null : '${localizations.nextMonthTooltip} ${localizations.formatMonthYear(_nextMonthDate)}',
|
child: new IconButton(
|
||||||
onPressed: _isDisplayingLastMonth ? null : _handleNextMonth,
|
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();
|
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