Reputation: 105
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
Reputation: 1
I know its probably late but using AutoTabsRouter.builder
fixed it for me.
Upvotes: 0