Flutter 如何从子小部件更改父 BottomNavigationBar 索引
Flutter how to change the parent BottomNavigationBar index from a child widget
所以我最近在 flutter 中开始了我的第一个项目,我完成了完整的 UI 布局,现在正在做前端的整个逻辑部分,我的大部分 onTap 行为都在工作,但我遇到下面的情况不知如何处理。
我有四个文件,其中包含所有 UI。
widget0.dart
widget1.dart
widget2.dart
这些文件每个都包含由 BottomNavigationBar 构建的 StatefullWidget。
main.dart
该文件包含我的 main() =>runApp class 和函数。我的 MaterialApp 包含一个带有 BottomNavigationBar 的脚手架。这按预期工作,我能够在 3 个小部件中的每一个之间切换。
但是在我的 widget0.dart 文件中我有一个按钮,它应该将我的 main.dart 文件中 BottomNavigationBar 的索引从 0 更改为 2(到从 widget2.dart).
构建小部件
我试图将保存导航栏索引的值包装在一个单独的静态 class 中,因此我可以 setState((){ StaticClass.index = 2})
在按钮 onTap() 中,但这没有不起作用,实际上将导航栏冻结为其初始值。
Whosebug 上某处的回答建议每个小部件都应该有自己的脚手架和导航栏,但我相信必须有更简洁的方法。
那么实现我的目标最Fluttery的方法是什么?
提前致谢。
您可以将函数作为参数传递给 widget0,在该函数中可以像这样更改索引值:
class ParentWidgetState extends State<ParentWidget> {
int _index = 0;
void goToWidget2() {
setState(() {
_index = 2;
});
}
Widget body() {
switch(_index) {
case 0:
return Widget0(goToWidget2);
case 1:
return Widget1();
case 2:
return Widget2();
}
return Container();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: body(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _index,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
),
],
),
);
}
}
class Widget0 extends StatelessWidget {
Widget0(this.goToWidget2);
final void Function() goToWidget2;
@override
Widget build(BuildContext context) {
return Center(child: FlatButton(
onPressed: goToWidget2,
child: Text("Go To Widget 2"),
),);
}
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("widget 1"),);
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("widget 2"),);
}
}
你可以用一个InheritedNotifier来控制索引。然后您就可以在您的应用中的任何位置访问它。
- 新建一个class
bottom_nav_scope.dart
import 'package:flutter/material.dart';
class BottomNavState extends ChangeNotifier {
int _navIndex = 0;
int get navIndex => _navIndex;
set navIndex(int value) {
_navIndex = value;
notifyListeners();
}
}
class BottomNavScope extends InheritedNotifier<BottomNavState> {
const BottomNavScope({
required BottomNavState notifier,
required Widget child,
Key? key,
}) : super(key: key, notifier: notifier, child: child);
static BottomNavState? of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<BottomNavScope>()
?.notifier;
}
}
- 用以下内容包装您的根有状态小部件(例如应用程序):
注意:这必须位于构建 BottomNavigationBar 的小部件之上。它还需要是一个有状态的小部件。
app.dart
final bottomNav = BottomNavState();
@override
Widget build(BuildContext context) {
BottomNavScope(notifier: bottomNav, child: ...). //wrap your root widget with this
- 在你的 BottomNavigationBar
BottomNavigationBar(
currentIndex: BottomNavScope.of(context)!.navIndex, ...)
- 用法
BottomNavScope.of(context)!.navIndex = 2;
所以我最近在 flutter 中开始了我的第一个项目,我完成了完整的 UI 布局,现在正在做前端的整个逻辑部分,我的大部分 onTap 行为都在工作,但我遇到下面的情况不知如何处理。
我有四个文件,其中包含所有 UI。
widget0.dart
widget1.dart
widget2.dart
这些文件每个都包含由 BottomNavigationBar 构建的 StatefullWidget。
main.dart
该文件包含我的 main() =>runApp class 和函数。我的 MaterialApp 包含一个带有 BottomNavigationBar 的脚手架。这按预期工作,我能够在 3 个小部件中的每一个之间切换。
但是在我的 widget0.dart 文件中我有一个按钮,它应该将我的 main.dart 文件中 BottomNavigationBar 的索引从 0 更改为 2(到从 widget2.dart).
构建小部件我试图将保存导航栏索引的值包装在一个单独的静态 class 中,因此我可以 setState((){ StaticClass.index = 2})
在按钮 onTap() 中,但这没有不起作用,实际上将导航栏冻结为其初始值。
Whosebug 上某处的回答建议每个小部件都应该有自己的脚手架和导航栏,但我相信必须有更简洁的方法。
那么实现我的目标最Fluttery的方法是什么?
提前致谢。
您可以将函数作为参数传递给 widget0,在该函数中可以像这样更改索引值:
class ParentWidgetState extends State<ParentWidget> {
int _index = 0;
void goToWidget2() {
setState(() {
_index = 2;
});
}
Widget body() {
switch(_index) {
case 0:
return Widget0(goToWidget2);
case 1:
return Widget1();
case 2:
return Widget2();
}
return Container();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: body(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _index,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
),
],
),
);
}
}
class Widget0 extends StatelessWidget {
Widget0(this.goToWidget2);
final void Function() goToWidget2;
@override
Widget build(BuildContext context) {
return Center(child: FlatButton(
onPressed: goToWidget2,
child: Text("Go To Widget 2"),
),);
}
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("widget 1"),);
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("widget 2"),);
}
}
你可以用一个InheritedNotifier来控制索引。然后您就可以在您的应用中的任何位置访问它。
- 新建一个class
bottom_nav_scope.dart
import 'package:flutter/material.dart';
class BottomNavState extends ChangeNotifier {
int _navIndex = 0;
int get navIndex => _navIndex;
set navIndex(int value) {
_navIndex = value;
notifyListeners();
}
}
class BottomNavScope extends InheritedNotifier<BottomNavState> {
const BottomNavScope({
required BottomNavState notifier,
required Widget child,
Key? key,
}) : super(key: key, notifier: notifier, child: child);
static BottomNavState? of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<BottomNavScope>()
?.notifier;
}
}
- 用以下内容包装您的根有状态小部件(例如应用程序):
注意:这必须位于构建 BottomNavigationBar 的小部件之上。它还需要是一个有状态的小部件。
app.dart
final bottomNav = BottomNavState();
@override
Widget build(BuildContext context) {
BottomNavScope(notifier: bottomNav, child: ...). //wrap your root widget with this
- 在你的 BottomNavigationBar
BottomNavigationBar(
currentIndex: BottomNavScope.of(context)!.navIndex, ...)
- 用法
BottomNavScope.of(context)!.navIndex = 2;