flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.13k stars 27.47k forks source link

FadeInImage support for crossfading between images #14790

Open btastic opened 6 years ago

btastic commented 6 years ago

Right now it is only possible to have a FadeInImage fade out to white and then fade in to the desired loaded image. It would be great if I can just crossfade between them if I wanted to.

https://material.io/guidelines/patterns/loading-images.html#loading-images-usage

Material guidelines state that the images can also transition.

xster commented 6 years ago

Does something like https://docs.flutter.io/flutter/widgets/AnimatedCrossFade-class.html work?

btastic commented 6 years ago

I had a look at that class, but I don't know how to make it work with network images.

Right now my code looks like this:

new FadeInImage(
  placeholder: new NetworkImageWithRetry(placeholderUrl),
  image: new NetworkImageWithRetry(imageUrl),
  fit: BoxFit.fill,
)

I'd have to change the AnimatedCrossFade state when the image changes right?

Herohtar commented 5 years ago

Just came across this trying to find out if there was some way to do a cross fade with FadeInImage. I'd like to see it support that, as the current fade-out-then-fade-in behavior is pretty ugly, IMO.

@btastic Maybe you already found a solution since it has been almost a year, but FadeInImage is implemented in Dart so you can take a look at the code to see how they listen for the NetworkImage completion. Also, as a simpler workaround, you can put the placeholder image in a Stack with the FadeInImage and use a transparent image for the placeholder there and set the fadeOutDuration to 0, kind of like this:

Stack(
  fit: StackFit.expand,
  children: <Widget>[
    Image.asset(placeholderAsset),
    FadeInImage.memoryNetwork(
      placeholder: Uint8List(512 * 512),
      image: imageUrl,
      fadeOutDuration: Duration(milliseconds: 0),
    ),
  ],
),

However, if you're using two network images, you're kind of doing it wrong because the whole point of FadeInImage is to have a local placeholder image that can be shown immediately until the network image loads. If you're loading the placeholder over the network too, it kind of defeats the purpose because now you have to wait for the placeholder to load as well.

Hixie commented 5 years ago

@apwilson What was the blend mode we ended up finding for doing a proper cross-fade? Do you remember?

lukepighetti commented 5 years ago

The fade-out and then fade-in behavior is pretty heinous for my use case (show a low res preview image and replace it with a high res image after its loaded). Removing fadeOutDuration adds flicker and still causes fade in from a blank background.

You can set fadeOutDuration and fadeInDuration to Duration.zero but now you don't have a FadeInImage, just a fallback image.

A Stack doesn't work in all situations. I have tightly controlled boxfit situation with a Hero image, and Stack blows widget chunks all over my project.

Finally, there's nothing wrong with using a network image for fallback when it's cached. This is a common pattern in my projects and it works beautifully.

@Hixie was there an implementation reason for the fade out and then fade in?

flschweiger commented 5 years ago

I also agree that the current implementation of FadeInImage does look a bit weird. Also most developers would expect a real cross-fade between the placeholder and the loaded image, not a fade out of the placeholder and then a fade in to the loaded image.

JulianHorst commented 5 years ago

I also agree regarding the desired outcome with FadeInImage.

https://flutter-cn.club/cookbook/images/fading-in-images/ This official "Stack approach" seems a bit weird, since it's adding another layer to the placeholder, which is transparent, so there happens fading, but actually it's the bottom of the Stack that is the placeholder

ryaanwells commented 4 years ago

Hey 👋 I've raised a PR to add this functionality over here. I'm keen to open a discussion on improving this area: splitting the animation strategy (fade out/fade in, crossfade, wipe, or any animation strategy of your choosing!) could make this area of code more extensible.

This is my first contribution so I'm not sure where the best place is for that conversation. @Hixie, would you recommend a design doc or is there a chat channel/mailing list that's more appropriate?

Cheers all!

jimmyff commented 2 years ago

Hey, could this get back on to a milestone?

It's crazy that this still doesn't crossfade between placeholder and image.

adifyr commented 1 year ago

How has this not been resolved yet? Does the Flutter Team not know the definition of "crossfade"? Get this back on a milestone asap.