14

In my flutter app, after the splash screen animation is finished, it pushes to the HomeRoute.

The HomeRoute has a backgropundImage which is intended to cover the whole screen:

HomeRoute.dart:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          decoration: BoxDecoration(
              image: DecorationImage(
                  image: AssetImage("assets/images/mainBgndsmall.png"),
                  fit: BoxFit.cover)),
          child: SafeArea(child: _buildBody())),
    );
  }

When the route is pushed, there is a white flicker before the backgroundImage is showed.

Is that a normal behavior or am I doing something wrong when trying to put an image as a background?

Image size is about 500KB or 600KB aprox. PNG image.

codeKiller
  • 5,493
  • 17
  • 60
  • 115

4 Answers4

1

The image has not loaded yet that is why the container loads before the image comes up

you can fix it by using a future builder which will display a circular progress indictor until the image is loaded and ready to be rendered

1

You can use precacheImage in your didChangeDependencies method to increase the chances of your image being loaded prior to the widget being displayed, preventing the white flicker.

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  precacheImage(const AssetImage("assets/images/mainBgndsmall.png"), context);
}

You may need to convert your widget to a StatefulWidget first in order to pass a BuildContext.

Chris Wickens
  • 156
  • 1
  • 8
1

It happens because the image is being loaded. Alternatively, you can use FutureBuilder Widget to handle images as they load here example

...
///future type variable to keep value from future method
late Future<String> futureData;

///future method to fetch some data
Future<String> getData(){
  ///give some duration before return value
  await Future.delayed(Duration(seconds: 1));
  
  //some code if you have some code
  // ....

  ///return string
  return "oke";
}

@override
didChangeDependencies(){
  super.didChangeDependencies();
  futureData = getData();
}

@override
Widget build(BuildContext context){
  Future.delayed(Duration(seconds: 1));
  return Scaffold(
    body: FutureBuilder<String>(
      future: futureData,
      builder:(context, snapshot) {
        ///if loading is done
        if(snapshot.connectionState == ConnectionState.done){
          // if future success
          if(snapshot.hasData){
            ///return widget what you want to show
            return Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              decoration: BoxDecoration(
                  image: DecorationImage(
                      image: AssetImage("assets/images/mainBgndsmall.png"),
                      fit: BoxFit.cover)),
              child: SafeArea(
                child: _buildBody()
              )
            );
          }else{
            // if future failed return some widget 
            return Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              child: Center(
                child: Text("Image can't load"),
              )
            );
          }
        }
        ///return progress loading
        return Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Center(
            child: CircularProgressIndicator(),
          )
        );
      },
    ),
  );
}
0

As of now it is considered as flutter framework bug. You can check that here. Also it is in Github open issue.

You can do one thing, You can use cached_network_image. While loading your image show your own container or whatever you want.

Pranav Dave
  • 393
  • 5
  • 7