我正在尝试做一个我认为非常简单的Flutter应用程序,但是我无法弄清楚我的代码出了什么问题。
我有一个带有抽屉小部件的Flutter应用程序。我正在使用此小部件来制作一个导航抽屉,抽屉的 child 有一个 ListView ,而 ListView 包含用户可以选择的 View 选项(A,B和C)。
由于应用程序的主页( MyHomePage )是从 StatefulWidget 扩展而来的,因此,我要加载新 View 的唯一操作是调用 setState 方法来分配“控制变量”的新值( viewName ),那么我希望Flutter会执行 MyHomePage 的 Widget build(BuildContext上下文)方法,但是这次使用新值 viewName 。
以上所有方法均按预期工作,但问题是在脚手架的正文字段中,我有一个 TabBarView 小部件,因为我想向用户显示带有两个选项卡的 View (选项卡1每个 View ( A,B和C )每个 View 的和选项卡2 。
TabBarView 子级是:
-的 StatefulTab 对象选项卡1
-用于的简单中心小部件Tab 2
我想在这里演示的是,当您点击抽屉的一个选项(例如,加载 B View )时,选项卡2 会按预期的值更改,但是选项卡1 (其中包含一个有状态窗口小部件),当您点击抽屉的任何其他选项时,其值不会更改
注:我必须对3个 View 使用相同的 StatefulTab 小部件,以便重复使用代码,因为3个 View 的唯一更改值是 viewName 变量。
这是代码:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/StatefulTab.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(viewName: 'A'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.viewName}) : super(key: key);
final String viewName;
@override
_MyHomePageState createState() => new _MyHomePageState(viewName: viewName);
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
String viewName;
_MyHomePageState({Key key, this.viewName});
TabController controller;
@override
void initState() {
super.initState();
controller = new TabController(
length: 2,
vsync: this,
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var tabs = <Tab>[
new Tab(icon: new Icon(Icons.home), text: 'Tab 1'),
new Tab(icon: new Icon(Icons.account_box), text: 'Tab 2')
];
return new Scaffold(
appBar: new AppBar(
title: new Text(viewName),
),
body: new TabBarView(controller: controller, children: <Widget>[
new StatefulTab(viewName: viewName),
new Center(child: new Text('This is the Tab 2 for view $viewName'))
]),
bottomNavigationBar: new Material(
color: Colors.blue,
child: new TabBar(controller: controller, tabs: tabs),
),
drawer: new Drawer(
child: new ListView(
children: <Widget>[
new Padding(
padding: new EdgeInsets.only(top: 50.0),
),
new ClipRect(
child: new Column(
children: <Widget>[
new ListTile(
title: new Text('Tap to load view: A'),
onTap: () => _loadView('A', context),
),
new ListTile(
title: new Text('Tap to load view: B'),
onTap: () => _loadView('B', context),
),
new ListTile(
title: new Text('Tap to load view: C'),
onTap: () => _loadView('C', context),
),
],
),
),
],
),
),
);
}
_loadView(String view, BuildContext context) {
Navigator.of(context).pop();
setState(() {
if (view == 'A') {
viewName = 'A';
} else if (view == 'B') {
viewName = 'B';
} else if (view == 'C') {
viewName = 'C';
}
});
}
}
StatefulTab.dart
import 'package:flutter/material.dart';
class StatefulTab extends StatefulWidget {
String viewName;
StatefulTab({Key key, this.viewName}) : super(key: key);
@override
StatefulTabState createState() => new StatefulTabState(viewName: viewName);
}
class StatefulTabState extends State<StatefulTab> {
String viewName;
StatefulTabState({Key key, this.viewName});
@override
Widget build(BuildContext context) {
return new Center(
child: new Text('This is the Tab 1 for View $viewName'),
);
}
}
我该如何告诉Flutter为标签1 的有状态wdiget取新值?
有没有更好的方法来实现带有动态 View 的导航抽屉?
提前致谢!
最佳答案
我想我找到了你的问题。您将viewName保留在主页中,另外还保留在StatefulTab中。这实际上是行不通的,因为对于StatefulTab,状态不会仅因为HomePage的状态发生变化而发生变化。通过在两个构建方法中插入打印语句得出了这个结论。 HomePage的构建方法根据您期望的行为(如您在支架的标题中已经看到的)起作用,但是StatefulTab的构建方法保持其状态。
进一步的调查和在不同地方的各种打印语句使我得出结论,即单击一个抽屉按钮后,不会调用StatefulTabState的构造函数。这是您的StatefulTab的工作示例:
class StatefulTab extends StatefulWidget {
String viewName;
StatefulTab({Key key, this.viewName}) : super(key: key);
@override
StatefulTabState createState() => new StatefulTabState();
}
class StatefulTabState extends State<StatefulTab> {
@override
Widget build(BuildContext context) {
return new Center(
child: new Text('This is the Tab 1 for View ${widget.viewName}'),
);
}
}
如有任何疑问,请随时评论。看看这个tutorial/documentation可能是有益的。