Flutter 自定义 AppBar 动作并将 Appbar 和 Body 一起传递给父级?

Posted

技术标签:

【中文标题】Flutter 自定义 AppBar 动作并将 Appbar 和 Body 一起传递给父级?【英文标题】:Flutter customize AppBar actions and pass Appbar & Body togehter up to parent? 【发布时间】:2021-07-23 23:11:24 【问题描述】:

我是 Flutter 的新手,我尝试构建一个应用程序,它以有状态小部件 TabScreen 作为主路由,其中​​包含一个 Scaffold。 Scaffold 的主体是根据底部导航栏中的选定索引构建的,效果很好。我的问题是 AppBar 的操作管理。 AppBar 应该为每个“主体屏幕”提供不同的操作,但这些操作会影响不同主体屏幕内的数据。

例如:在 Screen1 类中,我们有一个变量 List list1。对于 Screen1,AppBar 应提供“清除列表 1”选项,以删除所有列表 1 项,但在 Screen2 上应提供“清除 Screen2 列表”选项。

我的想法是创建一个新的 AppBar 类,将其导入我的 Screen1、Screen2、Screen3 类中,并按照this 帖子中的说明在这些屏幕中创建和配置 appBar。 有没有一种方法可以在我的 Screen1 类中不仅定义正文,还定义 AppBar 并将它们都返回到 TabScreen 父级?我认为这将是最简单的解决方案,但我不知道如何做得更好。

    class _TabScreenState extends State<TabScreen> 
    
    int _selectedPageIndex;

    final List<Map<String, Object>> _pages = [
        
          'page': Screen1(),
          'title': 'Screen1',
        ,
        
          'page': Screen2(),
          'title': 'Screen2',
        ,
        
          'page': Screen3(),
          'title': 'Screen3',
        ,
      ];
    
    @override
      Widget build(BuildContext context) 
    
    final appBar = AppBar(
          title: Text('Screen X'),
          actions: [
            PopupMenuButton(
              onSelected: (selectedValue) 
                setState(() 
                  if (selectedValue == 0) 
                    filterOn = true;
                    Provider.of<Screen1Data>(context, listen: false).clear();
                   else 
                    Provider.of<Screen1Data>(context, listen: false).reset();
                    filterOn = false;
                  
                );
              ,
              icon: Icon(Icons.more_vert),
              itemBuilder: (_) => [
                PopupMenuItem(child: Text('Reset'), value: 0),
                PopupMenuItem(
                    child: Text('Clear List'), value: 1),
              ],
            ),
          ],
        );
    
    
    return Scaffold(
          appBar: appBar,
          body: _pages[_selectedPageIndex]['page'],
          bottomNavigationBar: bottomBar,
        ); 

Screen1 内容可能如下所示:

class Screen1 extends StatefulWidget 

  @override
  _Screen1State createState() => _Screen1State();


class _Screen1State extends State<Screen1> 
  List<String> list1;
  
  @override
  Widget build(BuildContext context) 
     return Text(list1[0]);
    


【问题讨论】:

【参考方案1】:

_pages list添加操作:

final List<Map<String, Object>> _pages = [
        
          'page': Screen1(),
          'title': 'Screen1',
          'actions': <Widget>[/* List of actions for screen1 */] //<-- optional just in case you need default actions that depend on parent as well
        ,
        
          'page': Screen2(),
          'title': 'Screen2',
          'actions': <Widget>[/* List of actions for screen2 */] //<-- optional just in case you need default actions that depend on parent as well
        ,
        
          'page': Screen3(),
          'title': 'Screen3',
          'actions': <Widget>[/* List of actions for screen3 */] //<-- optional just in case you need default actions that depend on parent as well
        ,
      ];

创建一个构建自定义应用栏的函数:

AppBar _buildAppBar(String title, List<Widget> actions) => AppBar(
  title = title,
  actions = actions,
);

然后在脚手架内,为每页构建自定义应用栏:

 return Scaffold(
          appBar: _buildAppBar(
                     title:  _pages[_selectedPageIndex]['title'],  
                     actions: _pages[_selectedPageIndex]['actions']
                     // or if you have specific actions that are only visible form this page you can do
                     actions: [
                       /* list of page1 only actions*/

                     ]
                     // or if you want to combine both default and specific actions you can do
                     actions: [
                       ... _pages[_selectedPageIndex]['actions'],
                       /* list of actions that are specific to page1*/

                     ]
                  ),
          body: _pages[_selectedPageIndex]['page'],
          bottomNavigationBar: bottomBar,
        ); 

现在您将在每页获得一个自定义应用栏,包括自定义操作

【讨论】:

您好,Younss,感谢您的回答!但我不明白我应该如何在我的父类中定义动作,因为我的父类不知道需要的变量,这些变量应该受到影响。例如:我无法在我的父级中创建 list1.add('hi') 操作,因为 list1 属于 _Screen1State 类。还是我错过了什么? _buildAppBar 需要操作列表(小部件)。如果您有从父级看不到的特定操作,您可以将它们传递给函数。我在_pages 列表中添加了actions 键,只是为了演示。让我更新答案以澄清;)检查更新的答案

以上是关于Flutter 自定义 AppBar 动作并将 Appbar 和 Body 一起传递给父级?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter CustomScrollView 自定义滑动效果

自定义 AppBar Flutter

Flutter:如何从 appbar 动作中显示快餐栏

Flutter:主从布局中的自定义 Appbar、浮动操作按钮和 BottomSheet

Flutter学习日记之自定义AppBar&顶部Tab切换

Flutter Appbar 标题灰色背景显示