当使用 BottomNavigationBar
在小部件之间切换时,我试图保留小部件页面的状态。我已经读过 here 说我可以使用 IndexedStack
来做到这一点,但是,这在我的情况下不起作用,原因有两个:
Scaffold
会重建,因为对于某些(但不是全部)页面,Scaffold
应该扩展:Scaffold( extendBody: _pageIndex == 1, ...)
这里有一个小例子,表明 IndexStack
没有按预期工作,因为 Scaffold
重建:
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _pageIndex = 1;
List<Widget> _pages = [Text("hi"), Counter()];
@override
Widget build(BuildContext context) {
return Scaffold(
extendBody: _pageIndex == 1,
appBar: AppBar(),
body: IndexedStack(
children: _pages,
index: _pageIndex,
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Goto 0',),
BottomNavigationBarItem(icon: Icon(Icons.business), label: 'Goto 1',),
],
currentIndex: _pageIndex,
onTap: (int index) {
setState(() {
_pageIndex = index;
});
print("idx " + _pageIndex.toString());
},
),
);
}
}
Demo showing that the state is not preserved
这是可以被任何其他有状态小部件替换的计数器:
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
//this part is not important, just to show that state is lost
class _CounterState extends State<Counter> {
int _count = 0;
@override
void initState() {
_count = 0;
super.initState();
}
@override
Widget build(BuildContext context) {
return Center(
child: TextButton(
child: Text("Count: " + _count.toString(), style: TextStyle(fontSize: 20),),
onPressed: () {
setState(() {
_count++;
});
},
),
);
}
}
答案 0 :(得分:1)
首先,好问题!诀窍是使用 KeyedSubtree,并根据页面是否已被访问而有条件地呈现页面。
您可以通过这种方式调整您的代码以实现您想要的行为:
class Page {
const Page(this.subtreeKey, {required this.child});
final GlobalKey subtreeKey;
final Widget child;
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
var _pageIndex = 1;
final _pages = [
Page(GlobalKey(), child: Text('Hi')),
Page(GlobalKey(), child: Counter()),
];
final _builtPages = List<bool>.generate(2, (_) => false);
@override
Widget build(BuildContext context) {
return Scaffold(
extendBody: _pageIndex == 1,
appBar: AppBar(),
body: Stack(
fit: StackFit.expand,
children: _pages.map(
(page) {
return _buildPage(
_pages.indexOf(page),
page,
);
},
).toList(),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Goto 0',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Goto 1',
),
],
currentIndex: _pageIndex,
onTap: (int index) {
setState(() {
_pageIndex = index;
});
print("idx " + _pageIndex.toString());
},
),
);
}
Widget _buildPage(
int tabIndex,
Page page,
) {
final isCurrentlySelected = tabIndex == _pageIndex;
_builtPages[tabIndex] = isCurrentlySelected || _builtPages[tabIndex];
final Widget view = KeyedSubtree(
key: page.subtreeKey,
child: _builtPages[tabIndex] ? page.child : Container(),
);
if (tabIndex == _pageIndex) {
return view;
} else {
return Offstage(child: view);
}
}
}
您应该能够修改此代码以添加更多选项卡、功能等。