ModalBarrier Scrim不涵盖Appbar

发布于 2025-01-24 12:15:08 字数 1346 浏览 0 评论 0原文

我有一个材料应用,它使用了一个带有脚手架的构建器。当我从页面导航到页面时,脚手架和应用程序栏不会重建,但是脚手架的主体确实可以:


import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:raven_front/pages/pages.dart';

Future<void> main() async {
  runApp(RavenMobileApp());
}

class RavenMobileApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/splash',
      routes: pages.routes(context),
      builder: (context, child) {
        return SafeArea(
            child: Scaffold(
          extendBodyBehindAppBar: false,
          appBar: BackdropAppBar(),      // pretty much regular app bar
          body: child!,                  // pages of app
        ));
      },
    );
  }
}

但是,当我在一个页面上,我需要显示底部的模态表或警报框,或scrim,它不适用于应用程序栏:

    await showModalBottomSheet<void>(
        context: context,
        elevation: 1,
        barrierColor: AppColors.black38,     // not applied to app bar
        shape: components.shape.topRounded,
        builder: (BuildContext context) {
         ... 
        });

​?

我尝试保存物料应用中使用的上下文(最高级别)中使用的上下文,并在模态表中使用了上下文,但这错误地说上下文没有导航器。我希望我能保持当前的设计,但以某种方式将其扩展到应用程序栏上。

I've got a MaterialApp which uses a builder with a scaffold in it. When I navigate from page to page the scaffold and app bar does not rebuild, but the body of the scaffold does:


import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:raven_front/pages/pages.dart';

Future<void> main() async {
  runApp(RavenMobileApp());
}

class RavenMobileApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/splash',
      routes: pages.routes(context),
      builder: (context, child) {
        return SafeArea(
            child: Scaffold(
          extendBodyBehindAppBar: false,
          appBar: BackdropAppBar(),      // pretty much regular app bar
          body: child!,                  // pages of app
        ));
      },
    );
  }
}

but when I'm on a page where I need to show a bottom modal sheet, or alert box, or anything with a scrim, it doesn't apply to the app bar:

scrim ignores app bar

for example, I might make the ModalBottomSheet this way

    await showModalBottomSheet<void>(
        context: context,
        elevation: 1,
        barrierColor: AppColors.black38,     // not applied to app bar
        shape: components.shape.topRounded,
        builder: (BuildContext context) {
         ... 
        });

With my setup of having a builder in the MaterialApp, how can I get the scrim to cover everything?

I tried saving the context used in the MaterialApp (highest level) and using that in the modal sheet, but that errored saying that context doesn't have a Navigator. I'm hoping I can keep the current design but extend the scrim over the app bar somehow.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疯到世界奔溃 2025-01-31 12:15:08

你能相信吗,我必须自己滚动。另一个选择是放弃问题中提到的构建器材料应用程序设计。这是我必须做的:

应用程序栏:

Stack(
  children: [
    appBar,
    AppBarScrim(),
  ])

应用程序bar scrim

class AppBarScrim extends StatefulWidget {
  const AppBarScrim({Key? key}) : super(key: key);

  @override
  State<AppBarScrim> createState() => _AppBarScrimState();
}

class _AppBarScrimState extends State<AppBarScrim> {
  late List listeners = [];
  final Duration waitForSheetDrop = Duration(milliseconds: 50);
  bool applyScrim = false;

  @override
  void initState() {
    super.initState();
    listeners.add(streams.app.scrim.listen((bool value) async {
      if (applyScrim && !value) {
        await Future.delayed(waitForSheetDrop);
        setState(() {
          applyScrim = value;
        });
      }
      if (!applyScrim && value) {
        setState(() {
          applyScrim = value;
        });
      }
    }));
  }

  @override
  void dispose() {
    for (var listener in listeners) {
      listener.cancel();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () async {
          Navigator.of(components.navigator.routeContext!).pop();
          streams.app.scrim.add(false);
        },
        child: AnimatedContainer(
          duration: waitForSheetDrop,
          color: applyScrim ? Colors.black38 : Colors.transparent,
          height: applyScrim ? 56 : 0,
        ));
  }
}
showDialog( // and show bottom modal sheet...
  ..
  builder: (BuildContext context) {
    streams.app.scrim.add(true);                      // trigger
    return AlertDialog(...);
  }).then((value) => streams.app.scrim.add(false));   // remove trigger

can you believe it, I had to roll my own. the other option was to abandon the builder material app design mentioned in the question. This is what I had to do:

app bar:

Stack(
  children: [
    appBar,
    AppBarScrim(),
  ])

app bar scrim

class AppBarScrim extends StatefulWidget {
  const AppBarScrim({Key? key}) : super(key: key);

  @override
  State<AppBarScrim> createState() => _AppBarScrimState();
}

class _AppBarScrimState extends State<AppBarScrim> {
  late List listeners = [];
  final Duration waitForSheetDrop = Duration(milliseconds: 50);
  bool applyScrim = false;

  @override
  void initState() {
    super.initState();
    listeners.add(streams.app.scrim.listen((bool value) async {
      if (applyScrim && !value) {
        await Future.delayed(waitForSheetDrop);
        setState(() {
          applyScrim = value;
        });
      }
      if (!applyScrim && value) {
        setState(() {
          applyScrim = value;
        });
      }
    }));
  }

  @override
  void dispose() {
    for (var listener in listeners) {
      listener.cancel();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () async {
          Navigator.of(components.navigator.routeContext!).pop();
          streams.app.scrim.add(false);
        },
        child: AnimatedContainer(
          duration: waitForSheetDrop,
          color: applyScrim ? Colors.black38 : Colors.transparent,
          height: applyScrim ? 56 : 0,
        ));
  }
}
showDialog( // and show bottom modal sheet...
  ..
  builder: (BuildContext context) {
    streams.app.scrim.add(true);                      // trigger
    return AlertDialog(...);
  }).then((value) => streams.app.scrim.add(false));   // remove trigger
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文