当您无法访问基架时,如何在 Flutter 中交换/删除应用栏中的操作?



我处于以下情况:

我有一个带有应用栏和选项卡栏的脚手架,在脚手架的主体中,我有一个带有两个有状态小部件作为选项卡的 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(),
],
),
),
);
}

现在每个小组件都必须定义自己的操作以添加到应用栏,如何习惯性地将正确的操作设置为父基架?我尝试创建自定义选项卡控制器并侦听事件,并在运行时交换按钮,但这似乎将责任赋予选项卡控制器在其子行为和内部逻辑上。 有没有办法从子小部件中查询基架并将操作设置为应用栏(最终结束浮动操作按钮((在我指的是FirstWidgetSecondWidget的示例中(。

我一直在寻找像Scaffold.of(context).setAppBarActions(...)这样的人. 我发现这个问题非常相似,但我不同意解决方案,因为它要求父亲脚手架具有知识(并生成(与其孩子相关的行为的小部件,我想避免它。

您可以使用包提供程序来获取Scaffold.of(context).setAppBarActions(...)等功能。

使用child对于避免每次希望重新生成AppBar时重新生成TabBarView非常重要。

FirstWidgetSecondWidget中访问context很痛苦,因为contextinitState中不可用,因此必须使用后帧回调。

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)"));
}
}

最新更新