Flutter - 带有 SafeArea 的系统栏颜色

kal*_*ehv 9 flutter

我正在尝试为SafeArea带有彩色系统栏的 flutter 应用程序添加小部件,但不知何故它们总是变黑。

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle.light.copyWith(
        systemNavigationBarIconBrightness: Brightness.dark,
        systemNavigationBarColor: kSurfaceColor,
        statusBarIconBrightness: Brightness.dark,
        statusBarColor: Colors.red, // Note RED here
      ),
    );

    return SafeArea(
      child: Scaffold(
        backgroundColor: kWhiteColor,
        appBar: _buildAppBar(context), // Title and Avatar are built here
        body: _buildBody(), // This function just returns blank Container for now
        floatingActionButton: _buildFAB(context),
        floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

这是我看到的 在此处输入图片说明

如果我包SafeArea里面Containercolor属性设置为白色,它的工作原理,但系统栏图标也变成白色 在此处输入图片说明

dav*_*cv5 7

基于@david-carrilho 的回答,我创建了这个简单的小部件

import 'package:flutter/material.dart';

class ColoredSafeArea extends StatelessWidget {
  final Widget child;
  final Color color;

  const ColoredSafeArea({Key key, @required this.child, this.color})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color ?? Theme.of(context).colorScheme.primaryVariant,
      child: SafeArea(
        child: child,
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,无论我在哪里使用SafeArea,我都会使用我的小包装小部件ColoredSafeArea

class MyExampleView extends StatelessWidget {
  const MyExampleView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ColoredSafeArea(
      child: Center(
        child: Text('Nice color bar'),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这样做的原因是因为它在您的内容后面创建了一个具有指定颜色的容器,然后SafeArea根据设备简单地添加必要的填充。


ven*_*nir 6

我知道这是一个老问题,但在阅读文档后,我想出了一个更完整的解决方案。

我的回答考虑以下几点:

  1. 不要将脚手架包裹到 SafeAreas 中;
  2. [iOS] 为你的脚手架涂上正确的颜色;
  3. [Android] 以编程方式设置系统栏。

1.正确使用SafeArea

SafeArea是一个小部件,它执行MediaQuery向您的应用程序添加一些适当的填充的操作。这应该发生在body您的Scaffold应用程序内部。像这样的事情将导致代码稍后不会意外中断:

return Scaffold(
  // ...
  body: SafeArea(                // your SafeArea should stay here
    child: YourWidget(),
  ),
);
Run Code Online (Sandbox Code Playgroud)

2.iOS 缺口

正如其他答案已经说过的那样,您只需绘制脚手架即可获得您想要的颜色。你的 Scaffold 应该包含一个backgroundColor属性(如果你有的话,你的 AppBar 也应该包含在内)。

return Scaffold(
  // ...
  backgroundColor: yourColor,    // the RED you need
  appBar: AppBar(                // if any
    backgroundColor: yourColor,  // maybe RED here, also
    // a system overlay option is included here, too, see 3.
    // ...
  ),
  body: SafeArea(                // your SafeArea should stay here
    child: YourWidget(),
  ),
);
Run Code Online (Sandbox Code Playgroud)

3.Android系统UI

正如 OP 所做的那样,您需要SystemChrome.setSystemUIOverlayStyle()解决与 Android 相关的系统栏绘制问题。

但是,文档指出,如果您有不同的颜色,则每当弹出或推送新页面/新路线时都应该以编程方式调用此方法Route

假设你有一个 2.0 Router;然后,您将编写其build方法,如下所示:

Widget build(BuildContext context) {
    Color overlayColor = ... your color ...;
    final systemBarColors = SystemUiOverlayStyle(
      systemNavigationBarColor: overlayColor,
      statusBarColor: overlayColor,
    );
    SystemChrome.setSystemUIOverlayStyle(systemBarColors);

    return AnnotatedRegion<SystemUiOverlayStyle>(
      value: systemBarColors,
      child: Navigator(
        key: navigatorKey,
        pages: _stack,
        onPopPage: _onPopPage,
      ),
    );
}
Run Code Online (Sandbox Code Playgroud)

这将确保每次弹出或推送新页面时,即调用build我们的方法时Router,Android系统栏和状态栏都会正确绘制。


小智 5

Container(
   color ...
      ),
      child: SafeArea(
        child: Scaffold(
          body: 
            AnnotatedRegion<SystemUiOverlayStyle>(
               value: SystemUiOverlayStyle.light,
               child: ...
Run Code Online (Sandbox Code Playgroud)

  • 欢迎来到 stackoverflow。除了您提供的答案之外,请考虑提供简要说明,说明原因以及如何解决该问题。 (8认同)
  • 我对此投了反对票。不要使用此解决方案,“SafeArea”应始终位于脚手架内。这会导致导航栏和系统栏无缘无故变黑。 (2认同)