[英]Preserve state of widget in flutter even though parent widget rebuilds
在使用 BottomNavigationBar 在小部件之間切換時,我試圖保留小部件頁面的BottomNavigationBar
。 我在這里讀到我可以使用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());
},
),
);
}
}
這是可以被任何其他有狀態小部件替換的計數器:
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++;
});
},
),
);
}
}
首先,好問題! 訣竅是使用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);
}
}
}
您應該能夠修改此代碼以添加更多選項卡、功能等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.