我处于以下情况:
我有一个带有应用栏和选项卡栏的支架,在支架的主体中,我的TabBarView带有两个有状态的小部件作为选项卡,如下所示
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(text: "First"),
Tab(text: "Second"),
],
),
),
body: TabBarView(
children: <Widget>[
FirstWidget(),
SecondWidget(),
],
),
),
);
}
现在,每个小部件都必须定义要添加到应用程序栏中的自己的 Action ,您如何习惯地将正确的 Action 设置给父支架?我尝试过创建一个自定义的tabController并侦听事件,并在运行时交换按钮,但是似乎在其子行为和内部逻辑上赋予了Tab Controller 以责任。
有没有一种方法可以查询支架并将操作设置为子控件内的应用程序栏(最终结束为 float actionButton)(在示例中,我指的是
FirstWidget
和SecondWidget
)。我一直在寻找
Scaffold.of(context).setAppBarActions(...)
这样的东西。我发现this question非常相似,但是我不同意该解决方案,因为它需要父脚手架具有与行为有关的知识(并生成)小部件,并且我希望避免这种情况。
最佳答案
您可以使用包提供程序来获取诸如Scaffold.of(context).setAppBarActions(...)
之类的功能。
使用child
对于避免每次您想要重建TabBarView
时都避免重建AppBar
很重要。
由于context
中没有FirstWidget
,因此无法访问SecondWidget
和context
中的initState
,因此必须使用后框架回调。
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
Future<void> main() async {
return runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return MaterialApp(
title: 'My App',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class ActionWidgets with ChangeNotifier {
List<Widget> _widgets = <Widget>[];
UnmodifiableListView<Widget> get widgets {
return UnmodifiableListView<Widget>(this._widgets);
}
set widgets(final List<Widget> widgets) {
this._widgets = widgets;
this.notifyListeners();
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return DefaultTabController(
length: 2,
child: MultiProvider(
providers: [
ChangeNotifierProvider<ActionWidgets>(
create: (final BuildContext buildContext) {
return ActionWidgets();
},
),
],
child: Consumer<ActionWidgets>(
builder: (final BuildContext context, final ActionWidgets actionWidgets, final Widget child) {
return Scaffold(
appBar: AppBar(
title: const Text("My Home Page"),
actions: actionWidgets.widgets,
bottom: TabBar(
tabs: [
Tab(text: "First (comm)"),
Tab(text: "Second (social)"),
],
),
),
body: child,
);
},
child: TabBarView(
children: <Widget>[
FirstWidget(),
SecondWidget(),
],
),
),
),
);
}
}
class FirstWidget extends StatefulWidget {
@override
_FirstWidgetState createState() {
return _FirstWidgetState();
}
}
class _FirstWidgetState extends State<FirstWidget> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((final Duration _) {
final ActionWidgets actionWidgets = Provider.of<ActionWidgets>(this.context, listen: false);
actionWidgets.widgets = <Widget>[
Icon(Icons.email),
Icon(Icons.phone),
];
});
}
@override
Widget build(BuildContext context) {
return Center(child: Text("First Widget (communication)"));
}
}
class SecondWidget extends StatefulWidget {
@override
_SecondWidgetState createState() {
return _SecondWidgetState();
}
}
class _SecondWidgetState extends State<SecondWidget> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((final Duration _) {
final ActionWidgets actionWidgets = Provider.of<ActionWidgets>(this.context, listen: false);
actionWidgets.widgets = <Widget>[
Icon(Icons.group),
Icon(Icons.person_add),
];
});
}
@override
Widget build(BuildContext context) {
return Center(child: Text("Second Widget (social)"));
}
}