RedLamp15
RedLamp15

Reputation: 105

Flutter Tab Navigation with auto_route, how to avoid transition on SliverAppBar

So I'm starting a project where the main page (HomeScreen) has a NavigationBar and several sub-screens. For the purpose of this demo, I have created two sub-screens called StarScreen and SquareScreen. Auto_Route is my router.

This is what I came up with:

@RoutePage()
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return AutoTabsRouter(
      routes: [
        StarRoute(),
        SquareRoute(),
      ],
      transitionBuilder: (context, child, animation) => FadeTransition(
        opacity: animation,
        child: child,
      ),
      builder: (BuildContext context, Widget child) {
        final tabsRouter = AutoTabsRouter.of(context);

        return Scaffold(
          body: child,
          bottomNavigationBar: NavigationBar(
            selectedIndex: tabsRouter.activeIndex,
            onDestinationSelected: (index) {
              tabsRouter.setActiveIndex(index);
            },
            destinations: GenerateDestinations(),
          ),
        );
      },
    );
  }
}

This works very well, and the sub-screens are blinking when transitioning but there is no transition on the navigation bar. Exactly what I want.

Now, I want to upgrade this with an AppBar. I could simply add an appBar: AppBar() to my Scaffold and that would be it. But it wouldn't work because I want to work with SliverAppBar and SliverList on my pages, so I need to put everything in a CustomScrollView. My approach is to integrate the CustomScrollView in the body of HomeScreen, and define the other Slivers in StarScreen and SquareScreen. So my HomeScreen would look like this:

@RoutePage()
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return AutoTabsRouter(
      routes: [
        StarRoute(),
        SquareRoute(),
      ],
      transitionBuilder: (context, child, animation) => FadeTransition(
        opacity: animation,
        child: child,
      ),
      builder: (BuildContext context, Widget child) {
        final tabsRouter = AutoTabsRouter.of(context);

        return Scaffold(
          body: SafeArea(
            child: CustomScrollView(
              slivers: [
                SliverAppBar(
                  floating: true,
                  snap: true,
                  title: Text(
                    'Title',
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.onPrimaryContainer,
                    ),
                  ),
                  backgroundColor:
                      Theme.of(context).colorScheme.primaryContainer,
                ),
                child, // Only this child should be refreshed when changing page
              ],
            ),
          ),
          bottomNavigationBar: NavigationBar(
            selectedIndex: tabsRouter.activeIndex,
            onDestinationSelected: (index) {
              tabsRouter.setActiveIndex(index);
            },
            destinations: GenerateDestinations(),
          ),
        );
      },
    );
  }
}

And my other screens would look something like that:

@RoutePage()
class StarScreen extends StatelessWidget {
  const StarScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return SliverList(
      delegate: SliverChildListDelegate(
        [
          Container(
            // ...
          ),
          // ...
        ],
      ),
    );
  }
}

Problem is that when I execute this I get an error like:

A RenderViewport expected a child of type RenderSliver but received a child of type RenderErrorBox.

So, I understand that Slivers are rendering differently than box-widgets (if it's the right term). I think this is why it doesn't work. But if I put the SliverList directly in the place of child in CustomScrollView (instead of importing it from another file) it works.

Should I declare my StarScreen stateless widget differently?

Do I have the right approach overall?

Upvotes: 0

Views: 354

Answers (1)

Abdelrahman Negm
Abdelrahman Negm

Reputation: 1

I know its probably late but using AutoTabsRouter.builder fixed it for me.

Upvotes: 0

Related Questions