Flutter TapBar Page white flicker on init

Viewed 82

I am using a TabBarView in my app like this:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          TabBarView(
            controller: _controller,
            physics: const NeverScrollableScrollPhysics(),
            children: const [
              WishlistsView(),
              FriendsView(),
              EventsView(),
              InboxView(),
              ProfileView(),
            ],
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: BottomNavBar(
              initialIndex: widget.navBarOption.index,
              onPageChanged: (index) => _tap(context, index),
            ),
          ),
        ],
      ),
    );
  }

  void _tap(BuildContext context, int index) => context.go(
        '/home/${BottomNavBarOption.values[index].name}',
      );

Now the problem is that when I go on another page the first time there is a very short white screen before the page is actually displayed.

Here is a ScreenVideo for a better understanding. This happens on both Web and iOS.

Why is that happening? Can I avoid that? As you can see the views are not very heavy.

All they have is basically a SVGPicture.asset :

class _WishlistsViewState extends State<WishlistsView>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      body: Stack(
        children: const [
          BackgroundImage(option: BackgroundImageOption.wishlists),
        ],
      ),
    );
  }
}
2 Answers

It is probably taking time to load svg on the first go and caching it for showing it later.. You can probably try OffStage Widget which should load the UI and just not display it.

class _WishlistsViewState extends State<WishlistsView>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      body: Offstage(
      offStage: false,
       child: Stack(
        children: const [
          BackgroundImage(option: BackgroundImageOption.wishlists),
        ],
      ),
     ),
    );
  }
}

as @Kaushik Chandru correctly pointed out: The SVG are the problem. They have to load first. To solve that issue, I used this really useful function precachePicture right before I actually call runApp:

for (BackgroundImageOption imageOption in BackgroundImageOption.values) {
  await precachePicture(
    ExactAssetPicture(
      SvgPicture.svgStringDecoderBuilder,
      imageOption.assetPath,
    ),
    null,
  );
}
Related