您将需要更好的状态管理方式。我建议您使用 BLoC 模式来管理此小部件中的导航更改。我将在此处放置一个简化示例,说明如何使用一些 cmets 和外部参考改进来做到这一点。
// An enum to identify navigation index
enum Navigation { TEXT, OVERVIEW, DETAILS, OTHER_PAGE}
class NavigationBloc {
//BehaviorSubject is from rxdart package
final BehaviorSubject<Navigation> _navigationController
= BehaviorSubject.seeded(Navigation.TEXT);
// seeded with inital page value. I'am assuming PAGE_ONE value as initial page.
//exposing stream that notify us when navigation index has changed
Observable<Navigation> get currentNavigationIndex => _navigationController.stream;
// method to change your navigation index
// when we call this method it sends data to stream and his listener
// will be notified about it.
void changeNavigationIndex(final Navigation option) => _navigationController.sink.add(option);
void dispose() => _navigationController?.close();
}
这个 bloc 类公开了一个流输出currentNavigationIndex。 HomeScreen 将成为此输出的侦听器,它提供有关必须在Scaffold 小部件主体上创建和显示的小部件的信息。请注意,流以 Navigation.TEXT 的初始值开始。
您的主页需要进行一些更改。现在我们使用 StreamBuilder 小部件创建并提供一个小部件到body 属性。换句话说,StreamBuilder 正在监听来自 bloc 的流输出,当接收到一些数据时,这些数据将是 Navigation enum 值,我们决定应该在正文上显示什么小部件。
class _HomePageState extends State<HomePage> {
final NavigationBloc bloc = new NavigationBloc();
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<Navigation>(
stream: bloc.currentNavigationIndex,
builder: (context, snapshot){
_selectedIndex = snapshot.data.index;
switch(snapshot.data){
case Navigation.TEXT:
return Text('Index 0');
case Navigation.OVERVIEW:
// Here a thing... as you wanna change the page in another widget
// you pass the bloc to this new widget for it's capable to change
// navigation values as you desire.
return Overview(bloc: bloc);
//... other options bellow
case Navigation.DETAILS:
return Details(/* ... */);
}
},
),
bottomNavigationBar: BottomNavigationBar(
//...
currentIndex: _selectedIndex,
onTap: (index) => bloc.changeNavigationIndex(Navigation.values[index]),
),
);
}
@override
void dispose(){
bloc.dispose();// don't forgot this.
super.dispoe();
}
}
由于您想在单击其他小部件中的特定项目时更改主页的正文小部件,例如Overview,那么您需要将块传递给这个新小部件,当您单击项目时,您需要放置新的数据到 Stream 中,主体将被刷新。请注意,这种将BLoC 实例发送到另一个小部件的方式并不是更好的方式。我建议你看看InheritedWidget 模式。我在这里以一种简单的方式这样做是为了不写一个已经是更大的答案......
class Overview extends StatelessWidget {
final NavigationBloc bloc;
Overview({this.bloc});
@override
Widget build(BuildContext context) {
return YourWidgetsTree(
//...
// assuming that when you tap on an specific item yout go to Details page.
InSomeWidget(
onTap: () => bloc.changeNavigationIndex(Navigation.DETAILS);
),
);
}
}
我知道这么多代码,这是一种复杂的方法,但它就是这样。 setState 调用不会解决您的所有需求。看看这个article 这是最好的和更大的之一,它以最少的细节谈论了我在这里写的所有内容。
祝你好运!