当您无法访问脚手架时,如何在应用栏中交换/删除操作?
Posted
技术标签:
【中文标题】当您无法访问脚手架时,如何在应用栏中交换/删除操作?【英文标题】:How do you swap/remove actions in the app bar in flutter when you have no access to the scaffold? 【发布时间】:2020-05-23 17:15:06 【问题描述】:我的情况如下:
我有一个带有 appbar 和标签栏的脚手架,在脚手架的主体中,我的 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(),
],
),
),
);
现在每个小部件都必须定义自己的操作以添加到应用栏,您如何习惯性地将正确的操作设置到父脚手架?我已经尝试创建一个自定义 tabController 并监听事件,并在运行时交换按钮,但它似乎赋予标签控制器对其子行为和内部逻辑的责任。
有没有办法从子小部件(在示例中我指的是FirstWidget
和SecondWidget
)中查询脚手架并将操作设置到应用栏(最终结束浮动操作按钮)。
我正在寻找类似Scaffold.of(context).setAppBarActions(...)
的东西。
我发现this question 非常相似,但是我不同意该解决方案,因为它要求父脚手架具有知识(并生成)具有与其子级相关的行为的小部件,我想避免它。
【问题讨论】:
【参考方案1】:您可以使用包提供程序来获得像Scaffold.of(context).setAppBarActions(...)
这样的功能。
使用child
很重要,以避免每次您希望AppBar
重建时都重建TabBarView
。
在FirstWidget
和SecondWidget
中访问context
很痛苦,因为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)"));
【讨论】:
setAppBarActions() 不存在 @chitgoks 这正是我回答这个问题的原因。 是的,没错。这很奇怪。必须安装提供程序只是为了公开来自不同类的方法以上是关于当您无法访问脚手架时,如何在应用栏中交换/删除操作?的主要内容,如果未能解决你的问题,请参考以下文章