blob: 682ef9d1a1c2df68850ebec4ea727e3b7cc6444f [file] [log] [blame]
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
/// An image that shows a [placeholder] widget while the target [image] is
/// loading, then fades in the new image when it loads.
/// This is similar to [FadeInImage] but the difference is that it allows you
/// to specify a widget as a [placeholder], instead of just an [ImageProvider].
/// It also lets you override the [child] argument, in case you want to wrap
/// the image with another widget, for example an [Ink.image].
class FadeInImagePlaceholder extends StatelessWidget {
const FadeInImagePlaceholder({
Key key,
@required this.image,
@required this.placeholder,
this.duration = const Duration(milliseconds: 500),
this.excludeFromSemantics = false,
}) : assert(placeholder != null),
assert(image != null),
super(key: key);
/// The target image that we are loading into memory.
final ImageProvider image;
/// Widget displayed while the target [image] is loading.
final Widget placeholder;
/// What widget you want to display instead of [placeholder] after [image] is
/// loaded.
/// Defaults to display the [image].
final Widget child;
/// The duration for how long the fade out of the placeholder and
/// fade in of [child] should take.
final Duration duration;
/// See [Image.excludeFromSemantics].
final bool excludeFromSemantics;
/// See [Image.width].
final double width;
/// See [Image.height].
final double height;
/// See [].
final BoxFit fit;
Widget build(BuildContext context) {
return Image(
image: image,
excludeFromSemantics: excludeFromSemantics,
width: width,
height: height,
fit: fit,
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) {
return this.child ?? child;
} else {
return AnimatedSwitcher(
duration: duration,
child: frame != null ? this.child ?? child : placeholder,