fixes FadeInImage for an edge case (#111035) (#113035)
Co-authored-by: Viren Khatri <44755140+werainkhatri@users.noreply.github.com>
diff --git a/packages/flutter/lib/src/widgets/fade_in_image.dart b/packages/flutter/lib/src/widgets/fade_in_image.dart
index ec42f66..d2e6913 100644
--- a/packages/flutter/lib/src/widgets/fade_in_image.dart
+++ b/packages/flutter/lib/src/widgets/fade_in_image.dart
@@ -539,7 +539,8 @@
@override
Widget build(BuildContext context) {
- if (widget.wasSynchronouslyLoaded || _placeholderOpacityAnimation!.isCompleted) {
+ if (widget.wasSynchronouslyLoaded ||
+ (_placeholderOpacityAnimation?.isCompleted ?? true)) {
return widget.target;
}
diff --git a/packages/flutter/test/widgets/fade_in_image_test.dart b/packages/flutter/test/widgets/fade_in_image_test.dart
index d0f3cd5..e3b13bd 100644
--- a/packages/flutter/test/widgets/fade_in_image_test.dart
+++ b/packages/flutter/test/widgets/fade_in_image_test.dart
@@ -198,6 +198,44 @@
expect(parts.target.opacity, 1);
});
+ // Regression test for https://github.com/flutter/flutter/issues/111011
+ testWidgets("FadeInImage's image obeys gapless playback when first image is cached but second isn't",
+ (WidgetTester tester) async {
+ final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
+ final TestImageProvider imageProvider = TestImageProvider(targetImage);
+ final TestImageProvider secondImageProvider = TestImageProvider(replacementImage);
+
+ // Pre-cache the initial image.
+ imageProvider.resolve(ImageConfiguration.empty);
+ imageProvider.complete();
+ placeholderProvider.complete();
+
+ await tester.pumpWidget(FadeInImage(
+ placeholder: placeholderProvider,
+ image: imageProvider,
+ ));
+ await tester.pumpAndSettle();
+
+ await tester.pumpWidget(FadeInImage(
+ placeholder: placeholderProvider,
+ image: secondImageProvider,
+ ));
+
+ FadeInImageParts parts = findFadeInImage(tester);
+ // Continually shows previously loaded image until the new image provider provides the image.
+ expect(parts.placeholder, isNull);
+ expect(parts.target.rawImage.image!.isCloneOf(targetImage), isTrue);
+ expect(parts.target.opacity, 1);
+
+ // Now, provide the image.
+ secondImageProvider.complete();
+ await tester.pump();
+
+ parts = findFadeInImage(tester);
+ expect(parts.target.rawImage.image!.isCloneOf(replacementImage), isTrue);
+ expect(parts.target.opacity, 1);
+ });
+
testWidgets("FadeInImage's placeholder obeys gapless playback", (WidgetTester tester) async {
final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
final TestImageProvider secondPlaceholderProvider = TestImageProvider(replacementImage);