全程internet和 stackoverflow我已经搜索并看到了很多解决嵌套导航问题的解决方案,其中包含用于 Flutter 应用程序的持久底部导航栏。其中一些使用带有 IndexedStack 或 PageView 等的导航器。所有这些都很好除了 他们将不必要地构建未选择的选项卡(有时甚至在每次切换选项卡时重建所有选项卡),从而使解决方案无法执行。我终于想出了一个解决方案——因为我自己也在努力解决这个问题。
最佳答案
该解决方案非常基础,但希望您能够在此基础上进行构建和调整。它实现了以下目标:
导入 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Widget> _pages;
List<BottomNavigationBarItem> _items = [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "Home",
),
BottomNavigationBarItem(
icon: Icon(Icons.messenger_rounded),
label: "Messages",
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: "Settings",
)
];
int _selectedPage;
@override
void initState() {
super.initState();
_selectedPage = 0;
_pages = [
MyPage(
1,
"Page 01",
MyKeys.getKeys().elementAt(0),
),
// This avoid the other pages to be built unnecessarily
SizedBox(),
SizedBox(),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: WillPopScope(
onWillPop: () async {
return !await Navigator.maybePop(
MyKeys.getKeys()[_selectedPage].currentState.context,
);
},
child: IndexedStack(
index: _selectedPage,
children: _pages,
),
),
bottomNavigationBar: BottomNavigationBar(
items: _items,
currentIndex: _selectedPage,
onTap: (index) {
setState(() {
// now check if the chosen page has already been built
// if it hasn't, then it still is a SizedBox
if (_pages[index] is SizedBox) {
if (index == 1) {
_pages[index] = MyPage(
1,
"Page 02",
MyKeys.getKeys().elementAt(index),
);
} else {
_pages[index] = MyPage(
1,
"Page 03",
MyKeys.getKeys().elementAt(index),
);
}
}
_selectedPage = index;
});
},
),
);
}
}
class MyPage extends StatelessWidget {
MyPage(this.count, this.text, this.navigatorKey);
final count;
final text;
final navigatorKey;
@override
Widget build(BuildContext context) {
// You'll see that it will only print once
print("Building $text with count: $count");
return Navigator(
key: navigatorKey,
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.text),
),
body: Center(
child: RaisedButton(
child: Text(this.count.toString()),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => MyCustomPage(count + 1, text)));
},
),
),
);
},
);
},
);
}
}
class MyCustomPage extends StatelessWidget {
MyCustomPage(this.count, this.text);
final count;
final text;
@override
Widget build(BuildContext parentContext) {
return Scaffold(
appBar: AppBar(
title: Text(this.text),
),
body: Column(
children: [
Expanded(
child: Container(
child: ListView.builder(
itemCount: 15,
itemBuilder: (context, index) {
return Container(
width: double.infinity,
child: Card(
child: Center(
child: RaisedButton(
child: Text(this.count.toString() + " pos($index)"),
onPressed: () {
Navigator.of(parentContext).push(MaterialPageRoute(
builder: (ctx) =>
MyCustomPage(count + 1, text)));
},
),
),
),
);
},
),
),
),
],
),
);
}
}
class MyKeys {
static final first = GlobalKey(debugLabel: 'page1');
static final second = GlobalKey(debugLabel: 'page2');
static final third = GlobalKey(debugLabel: 'page3');
static List<GlobalKey> getKeys() => [first, second, third];
}
关于Flutter:具有持久性BottomNavigationBar 的嵌套路由,但不会不必要地构建未选择的页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66404759/