是否可以从Scaffold小部件中的主体传递AppBar? [英] Is it possible to pass AppBar from body in Scaffold widget?

查看:81
本文介绍了是否可以从Scaffold小部件中的主体传递AppBar?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有drawerScaffold小部件.我需要在body中显示的屏幕具有不同的AppBars(其中一些具有PageView的指示符,其中一些是单页的,某些中具有徽标). 因此,我没有将任何AppBar传递给我的Scaffold,而是将其包含在我在body中使用的小部件中.但是抽屉里没有汉堡图标.

是否可以将此AppBar从我的body小部件传递到包含它的Scaffold?

或者,如果有一种更好的小部件组合方式来解决这种情况,我想尝试一下.

UPD

有一种很好的方式来显示

BottomSheet操作系统SnackBar

Scaffold.of(context)
    .showSnackBar(SnackBar(content: Text('Processing Data')));

不幸的是,AppBar并非如此.

解决方案

似乎您希望全局Scaffold在切换页面时保持不变.在这种情况下,您必须编写自己的逻辑以使菜单按钮出现:

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) {
        // wrap a scaffold around the Navigator so that it is the same for all pages
        return Scaffold(
          body: AppScaffold(child: child),
          drawer: Drawer(),
        );
      },
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: buildLeadingAction(context),
        title: Text('Home'),
      ),
    );
  }
}

/// Makes it easier to access the outer scaffold with the drawer from any context
class AppScaffold extends InheritedWidget {
  const AppScaffold({Key key, @required Widget child})
      : assert(child != null),
        super(key: key, child: child);

  /// nullable
  static ScaffoldState of(BuildContext context) {
    return context
        .ancestorInheritedElementForWidgetOfExactType(AppScaffold)
        ?.ancestorStateOfType(const TypeMatcher<ScaffoldState>());
  }

  @override
  bool updateShouldNotify(AppScaffold old) => false;
}

/// This is a simple method and not a widget
/// so that null can be returned if no AppScaffold with a drawer was found
Widget buildLeadingAction(BuildContext context) {
  final ScaffoldState appScaffold = AppScaffold.of(context);
  if (appScaffold != null && appScaffold.hasDrawer) {
    return IconButton(
      icon: const Icon(Icons.menu),
      onPressed: () => appScaffold.openDrawer(),
      tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
    );
  } else {
    return null;
  }
}

或者,您也可以将抽屉的Scaffold放置在页面的内部,并使用GlobalKey来访问其ScaffoldState.

I have a Scaffold widget with drawer. The screens I need to show in body have different AppBars (some of them have indicators for PageView, some of them are single paged, some have logo in it). So I do not pass any AppBar to my Scaffold but include it in widget I use in body. But there is no hamburger icon for drawer and it.

Is it possible to pass this AppBar from my body widget to the Scaffold containing it?

Or if there is a better way of widgets composition to solve this scenario I'd like to give it a try.

UPD

There is a nice way to show BottomSheet os SnackBar with

Scaffold.of(context)
    .showSnackBar(SnackBar(content: Text('Processing Data')));

Unfortunately it is not the case for AppBar.

解决方案

It seems like you want a global Scaffold that stays the same when you switch pages. In that case you have to write your own logic to make the menu button appear:

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) {
        // wrap a scaffold around the Navigator so that it is the same for all pages
        return Scaffold(
          body: AppScaffold(child: child),
          drawer: Drawer(),
        );
      },
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: buildLeadingAction(context),
        title: Text('Home'),
      ),
    );
  }
}

/// Makes it easier to access the outer scaffold with the drawer from any context
class AppScaffold extends InheritedWidget {
  const AppScaffold({Key key, @required Widget child})
      : assert(child != null),
        super(key: key, child: child);

  /// nullable
  static ScaffoldState of(BuildContext context) {
    return context
        .ancestorInheritedElementForWidgetOfExactType(AppScaffold)
        ?.ancestorStateOfType(const TypeMatcher<ScaffoldState>());
  }

  @override
  bool updateShouldNotify(AppScaffold old) => false;
}

/// This is a simple method and not a widget
/// so that null can be returned if no AppScaffold with a drawer was found
Widget buildLeadingAction(BuildContext context) {
  final ScaffoldState appScaffold = AppScaffold.of(context);
  if (appScaffold != null && appScaffold.hasDrawer) {
    return IconButton(
      icon: const Icon(Icons.menu),
      onPressed: () => appScaffold.openDrawer(),
      tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
    );
  } else {
    return null;
  }
}

Alternatively you can also place the Scaffold for the drawer inside of the page, and use a GlobalKey to access its ScaffoldState.

这篇关于是否可以从Scaffold小部件中的主体传递AppBar?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆