我正在学习 Flutter 并且正在努力解决一些状态管理问题。
我有一个 HomeScreen 小部件,其中包含 Scaffold 和一个 BottomNavigationBar。要根据BottomNavigationBar 中选定的选项卡切换页面,我将PageView 与PageController 一起使用。以下是 HomeScreen 小部件的 build
方法的外观:
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: _currentIndex == 2,
appBar: AppBar(...properties),
body: PageView(
controller: _pageController,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[...items],
currentIndex: _currentIndex,
onTap: _onItemTapped, //This changes state _currentIndex and calls the method _pageController.jumpToPage(_currentIndex);
),
);
}
_currentIndex
最初为 0。_pages
是一个包含 3 个小部件的列表。_pageController
是一个简单的 PageController,initialPage 设置为 0。如果您注意到我正在使用使用 extendBodyBehindAppBar: _currentIndex == 2
状态的属性 _currentIndex
,这会导致问题。
当我点击 BottomNavigationBar 上的最后一个 Tab 时,状态 _currentIndex
更改为 2,因此 extendBodyBehindAppBar
设置为 true
,这使得整个 Scaffold 重建自身,PageView 的状态为丢失了。
如果注释掉 extendBodyBehindAppBar: _currentIndex == 2
行,那么即使 Scaffold 重建了 PageView 小部件的状态。
据我所知,即使父级重建,Flutter 也应该保持子级 Widgets 的状态,因为 WidgetTree 没有改变或重新排列。我尝试在 PageView 上使用 Key 但没有任何效果。
非常感谢任何帮助。
答案 0 :(得分:0)
参考Lucas Salton Cardinali post on medium 你需要使用PageStorage来持久化你需要的child被销毁后的状态。
这里是从同一页面检索的示例:
import 'package:flutter/material.dart';
// ...
void main() => runApp(MyApp());
// ...
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Widget> pages = <Widget>[
ColorBoxPage(
key: PageStorageKey('pageOne'),
),
ColorBoxPage(
key: PageStorageKey('pageTwo'),
)
];
int currentTab = 0;
final PageStorageBucket _bucket = PageStorageBucket();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Persistence Example"),
),
body: PageStorage(
child: pages[currentTab],
bucket: _bucket,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (int index) {
setState(() {
currentTab = index;
});
},
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'page2',
),
],
),
);
}
}
class ColorBoxPage extends StatelessWidget {
ColorBoxPage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
itemExtent: 250.0,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(10.0),
child: Material(
color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
child: Center(
child: Text(index.toString()),
),
),
),
);
}
}