所以我正在启动一个项目,其中主页(
HomeScreen
)有一个NavigationBar
和几个子屏幕。为了本演示的目的,我创建了两个子屏幕,名为 StarScreen
和 SquareScreen
。 Auto_Route是我的路由器。
这就是我想到的:
@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(),
),
);
},
);
}
}
效果很好,过渡时子屏幕会闪烁,但导航栏上没有过渡。正是我想要的。
现在,我想用 AppBar 来升级它。我可以简单地在我的脚手架中添加一个
appBar: AppBar()
就这样了。但它不起作用,因为我想在我的页面上使用 SliverAppBar 和 SliverList,所以我需要将所有内容放在 CustomScrollView
中。我的方法是将CustomScrollView
整合到HomeScreen
的主体中,并在StarScreen
和SquareScreen
中定义其他Sliver。所以我的HomeScreen
看起来像这样:
@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(),
),
);
},
);
}
}
我的其他屏幕看起来像这样:
@RoutePage()
class StarScreen extends StatelessWidget {
const StarScreen({super.key});
@override
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildListDelegate(
[
Container(
// ...
),
// ...
],
),
);
}
}
问题是,当我执行此操作时,我收到如下错误:
A RenderViewport expected a child of type RenderSliver but received a child of type RenderErrorBox.
所以,我知道 Slivers 的渲染方式与 box-widgets 不同(如果这是正确的术语)。我认为这就是它不起作用的原因。但是,如果我将 SliverList 直接放在
child
中 CustomScrollView
的位置(而不是从另一个文件导入),它就可以工作。
我应该以不同的方式声明我的
StarScreen
无状态小部件吗?
总体来说我的方法正确吗?
我知道它可能已经晚了,但使用
AutoTabsRouter.builder
为我修复了它。