Avoid including a potentially animated invisible image (#50842)

* Avoid including a potentially animated invisible image
This commit is contained in:
Dan Field 2020-02-18 11:29:55 -08:00 committed by GitHub
parent e4fbb1aba6
commit 8aa67610f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 6 deletions

View File

@ -448,7 +448,13 @@ class _AnimatedFadeOutFadeInState extends ImplicitlyAnimatedWidgetState<_Animate
tween: ConstantTween<double>(0), tween: ConstantTween<double>(0),
weight: widget.fadeInDuration.inMilliseconds.toDouble(), weight: widget.fadeInDuration.inMilliseconds.toDouble(),
), ),
])); ]))..addStatusListener((AnimationStatus status) {
if (_placeholderOpacityAnimation.isCompleted) {
// Need to rebuild to remove placeholder now that it is invisibile.
setState(() {});
}
});
_targetOpacityAnimation = animation.drive(TweenSequence<double>(<TweenSequenceItem<double>>[ _targetOpacityAnimation = animation.drive(TweenSequence<double>(<TweenSequenceItem<double>>[
TweenSequenceItem<double>( TweenSequenceItem<double>(
tween: ConstantTween<double>(0), tween: ConstantTween<double>(0),
@ -472,6 +478,15 @@ class _AnimatedFadeOutFadeInState extends ImplicitlyAnimatedWidgetState<_Animate
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final Widget target = FadeTransition(
opacity: _targetOpacityAnimation,
child: widget.target,
);
if (_placeholderOpacityAnimation.isCompleted) {
return target;
}
return Stack( return Stack(
fit: StackFit.passthrough, fit: StackFit.passthrough,
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
@ -479,10 +494,7 @@ class _AnimatedFadeOutFadeInState extends ImplicitlyAnimatedWidgetState<_Animate
// but it allows the Stack to avoid a call to Directionality.of() // but it allows the Stack to avoid a call to Directionality.of()
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
children: <Widget>[ children: <Widget>[
FadeTransition( target,
opacity: _targetOpacityAnimation,
child: widget.target,
),
FadeTransition( FadeTransition(
opacity: _placeholderOpacityAnimation, opacity: _placeholderOpacityAnimation,
child: widget.placeholder, child: widget.placeholder,

View File

@ -209,6 +209,28 @@ Future<void> main() async {
expect(findFadeInImage(tester).state, same(state)); expect(findFadeInImage(tester).state, same(state));
}); });
testWidgets('does not keep the placeholder in the tree if it is invisible', (WidgetTester tester) async {
final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
final TestImageProvider imageProvider = TestImageProvider(targetImage);
await tester.pumpWidget(FadeInImage(
placeholder: placeholderProvider,
image: imageProvider,
fadeOutDuration: animationDuration,
fadeInDuration: animationDuration,
excludeFromSemantics: true,
));
placeholderProvider.complete();
await tester.pumpAndSettle();
expect(find.byType(Image), findsNWidgets(2));
imageProvider.complete();
await tester.pumpAndSettle();
expect(find.byType(Image), findsOneWidget);
});
testWidgets('re-fades in the image when the target image is updated', (WidgetTester tester) async { testWidgets('re-fades in the image when the target image is updated', (WidgetTester tester) async {
final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage); final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
final TestImageProvider imageProvider = TestImageProvider(targetImage); final TestImageProvider imageProvider = TestImageProvider(targetImage);
@ -285,7 +307,7 @@ Future<void> main() async {
expect(findFadeInImage(tester).target.opacity, moreOrLessEquals(1)); expect(findFadeInImage(tester).target.opacity, moreOrLessEquals(1));
}); });
group(ImageProvider, () { group('ImageProvider', () {
testWidgets('memory placeholder cacheWidth and cacheHeight is passed through', (WidgetTester tester) async { testWidgets('memory placeholder cacheWidth and cacheHeight is passed through', (WidgetTester tester) async {
final Uint8List testBytes = Uint8List.fromList(kTransparentImage); final Uint8List testBytes = Uint8List.fromList(kTransparentImage);