如果我使用PageView(内部带有ListView)+ BottomNavBar,则一切正常。 我对每个页面都使用唯一的PageStorageKey,因此两个页面上的ListViews都可以保存和恢复滚动偏移。
但是我需要基于路线构建应用程序导航。 这是一个非常简化的代码,但这足以显示和重现我所遇到的问题。 您可以复制并粘贴此片段,然后检查
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: Text("Test")),
body: Scaffold(
body: Navigator(
key: _navigatorKey,
onGenerateRoute: (settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => SomeWidget(0));
case '/another_route':
return MaterialPageRoute(builder: (_) => SomeWidget(1));
break;
}
},
),
bottomNavigationBar: BottomNavigationBar(
selectedItemColor: Colors.grey,
unselectedItemColor: Colors.grey,
items: [
BottomNavigationBarItem(icon: Icon(Icons.print), title: Text('Page 0')),
BottomNavigationBarItem(icon: Icon(Icons.category), title: Text('Page 1')),
],
onTap: (index) {
if (index == 0) {
_navigatorKey.currentState.pushReplacementNamed('/');
} else {
_navigatorKey.currentState.pushReplacementNamed('/another_route');
}
},
),
),
),
);
}
}
class SomeWidget extends StatelessWidget {
final int page;
SomeWidget(this.page) : super(key: Key('page key $page'));
@override
Widget build(BuildContext context) {
return ListView.builder(
key: PageStorageKey(page),
itemBuilder: (context, index) {
return Card(
key: Key('item: $index on page: $page'),
color: page == 0 ? Colors.blue[200] : Colors.green[200],
child: Container(
height: 196,
alignment: Alignment.center,
child: Text('Row: $index | Page $page'),
),
);
},
);
}
}
PS:出于某些原因,我不想为此使用PageView。我相信BottomNavBar应该触发本地导航器以替换不同的页面进行推送。
我认为这是非常方便的方式,而且我可以轻松更改页面之间的导航过渡。在我的情况下,我使用FadeIn +比例转换,但是在上面的示例代码中,我忽略了这一点,因为它不会影响最终结果。
是的,我了解PageStorageKey,但是它无济于事。
答案 0 :(得分:0)
这是预期的行为。按下屏幕时,它将构建一个全新的屏幕,而没有任何以前的状态。
这就是为什么使用综合浏览量的原因,它是为了保留状态而不会卸载任何屏幕。
在您的示例中,生命周期为
布置屏幕
构建新屏幕
显示屏幕
我可以共享我的使用方式,而无需使用viewpager(因为我不需要拖动功能)。
import 'package:flutter/material.dart';
import '../Widgets.dart'; // my custom widgets
class PageTabs extends StatefulWidget {
@override
_PageTabsState createState() => _PageTabsState();
}
class _PageTabsState extends State<PageTabs> {
int _cIndex = 0; //the current page index
@override
void initState() {
super.initState();
}
void _changeTab(index) {
setState(() {
_cIndex = index;
});
}
List<Widget> tabs = [
TimelineScreen(key: PageStorageKey('TimeLine')),
PageTrends(key: PageStorageKey('Trends')),
PageSettings(key: PageStorageKey('Settings'))
];
final PageStorageBucket bucket = PageStorageBucket();
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: 1,
length: 3,
child: Stack(
alignment: AlignmentDirectional.bottomStart,
children: <Widget>[
PageStorage(
child: tabs[_cIndex],
bucket: bucket,
),
AppBarra( //Custom bottom navigation bar wrapper
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: TabButton(
tooltip: 'Back',
onTap: () {
_changeTab(0);
},
icon: Icons.home,
color:
_cIndex == 0 ? Color(0xff00abee) : Colors.grey)),
Expanded(
child: TabButton(
tooltip: 'Back',
onTap: () {
_changeTab(1);
},
icon: Icons.search,
color:
_cIndex == 1 ? Color(0xff00abee) : Colors.grey)
),
Expanded(
child: TabButton(
tooltip: 'Back',
onTap: () {
_changeTab(2);
},
icon: Icons.settings,
color:
_cIndex == 2 ? Color(0xff00abee) : Colors.grey)),
]))
]
));
}
}
我使用pageStorage来保存状态,使用堆栈以避免使用脚手架(因为在页面中放置另一个脚手架时会导致奇怪的颜色错误),并使用自定义应用栏为我完成一些样式设置(自定义材质标高阴影颜色]。
您可以尝试自己弄清楚它,这里的重要部分是一起使用pageStorage,存储桶和PageStorageKey来保留滚动位置