【问题标题】:Flutter - How to set status bar color when AppBar not presentFlutter - 如何在 AppBar 不存在时设置状态栏颜色
【发布时间】:2018-11-03 05:39:43
【问题描述】:

当 AppBar 不存在时如何设置状态栏颜色。

我试过了,但没有用。

Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
    return new Scaffold(
        body: new Container(
        color: UniQueryColors.colorBackground,
        child: new ListView.builder(
           itemCount: 7,
           itemBuilder: (BuildContext context, int index){
             if (index == 0){
               return addTopInfoSection();
             }
           },
        ),
       ),
    );
}

输出如下所示:

【问题讨论】:

  • 你是如何管理状态栏的空间,防止内容重叠的?
  • @Hannes.T 使用我上面的代码
  • 我不会放弃你添加蓝色容器不重叠的额外填充/边距的地方
  • @Hannes.T 对于 Android,这是默认设置。对于 iOS,我认为您可能需要检查 MediaQuery.of(context).padding.top
  • 您可以将内容包装在 SafeArea 小部件 @Hannes.T

标签: dart flutter statusbar


【解决方案1】:

状态栏颜色由安卓系统渲染。是否可以从 Flutter 中设置还有待商榷:How to make Android status bar light in Flutter

不过,您可以通过编辑主题更改 Android 特定代码中的状态栏颜色:How to change the status bar color in android

对于 iOS,您必须查看他们的文档 - 我不熟悉该平台。

实际上有两个 Dart 库,一个用于设置light/dark theme of the statusbar,另一个用于设置setting the colour。我也没有使用过,但显然其他人也遇到了与您相同的问题并最终开发了自己的软件包。

【讨论】:

  • 感谢您的建议。我会检查他们。
【解决方案2】:

在 Android 上,在 MainActivity.java 中的 onCreate 中,在调用 super.onCreate(savedInstanceState); 之后添加以下内容;

getWindow().setStatusBarColor(0x00000000);

或者你可以使用flutter_statusbarcolor插件

   changeStatusColor(Color color) async {
    try {
      await FlutterStatusbarcolor.setStatusBarColor(color);
    } on PlatformException catch (e) {
      print(e);
    }
  }

Sample project

【讨论】:

  • 感谢您的建议。我会检查他们。
【解决方案3】:

首先,导入services包:

import 'package:flutter/services.dart';

接下来,只需将其放入您应用的构建函数

SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
  statusBarColor: Colors.blue, //or set color with: Color(0xFF0000FF)
));

此外,您还可以设置有用的属性,例如:statusBarIconBrightnesssystemNavigationBarColorsystemNavigationBarDividerColor


如果您更喜欢 flutter/widget 方式来做同样的事情,请考虑使用 AnnotatedRegion<SystemUiOverlayStyle> 小部件。

value: 属性可以设置为包含如上所示相同属性的SystemUiOverlayStyle() 对象。


欲了解更多信息,请前往API Docs

【讨论】:

  • 添加导入语句:import 'package:flutter/services.dart';
  • 这不适用于导航,或者在某些情况下似乎根本不起作用。我用Jordy Sinke 的回答添加了更好的结果,这也让人感觉更飘忽。
  • 有人提到这仅适用于android而不适用于ios。 T/F ?
  • 这是否以编程方式工作?就像我/用户在明暗模式之间切换主题时一样?我注意到其中一些选项仅适用于重建。
  • statusBarColor 仅适用于 Android 版本 M 及更高版本,不支持 iOS。
【解决方案4】:

在搜索 SystemChrome 时,我发现了这个:https://docs.flutter.io/flutter/services/SystemChrome/setSystemUIOverlayStyle.html

示例代码的正上方是关于AppBar.brightness 的一段。

您应该可以像这样添加 AppBar:

Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
    return new Scaffold(
        appBar: new AppBar(
            title: new Text('Nice title!'),
            brightness: Brightness.light,
        ),
        body: new Container(
        color: UniQueryColors.colorBackground,
        child: new ListView.builder(
           itemCount: 7,
           itemBuilder: (BuildContext context, int index){
             if (index == 0){
               return addTopInfoSection();
             }
           },
        ),
       ),
    );
}

这里有关于Brightness的信息

【讨论】:

    【解决方案5】:
    Widget build(BuildContext context) {
    
        return new Scaffold(
            body: new Container(
                color: UniQueryColors.colorBackground,
    
        /* Wrapping ListView.builder with MediaQuery.removePadding() removes the default padding of the ListView.builder() and the status bar takes the color of the app background */
    
            child: MediaQuery.removePadding(
             removeTop: true,
             context: context,
            child: ListView.builder(
               itemCount: 7,
               itemBuilder: (BuildContext context, int index){
                 if (index == 0){
                   return addTopInfoSection();
                 }
               },
            ),
           ),
          ),
        );
    }
    

    【讨论】:

      【解决方案6】:

      这里可以使用flutter flutter_statusbar_manager 1.0.2 lib

      Flutter 状态栏管理器,让您可以跨 iOS 和 Android 控制状态栏颜色、样式(主题)、可见性和半透明属性。为 Android 控制导航栏提供了一些额外的好处。

      import 'package:flutter/material.dart';
      import 'dart:async';
      
      import 'package:flutter/services.dart';
      import 'package:flutter_statusbar_manager/flutter_statusbar_manager.dart';
      
      void main() => runApp(new MyApp());
      
      class MyApp extends StatefulWidget {
        MyApp();
      
        factory MyApp.forDesignTime() {
          // TODO: add arguments
          return new MyApp();
        }
      
        @override
        _MyAppState createState() => new _MyAppState();
      }
      
      class _MyAppState extends State<MyApp> {
        double _statusBarHeight = 0.0;
        bool _statusBarColorAnimated = false;
        Color _statusBarColor = Colors.black;
        double _statusBarOpacity = 1.0;
        bool _statusBarHidden = false;
        StatusBarAnimation _statusBarAnimation = StatusBarAnimation.NONE;
        StatusBarStyle _statusBarStyle = StatusBarStyle.DEFAULT;
        bool _statusBarTranslucent = false;
        bool _loadingIndicator = false;
        bool _fullscreenMode = false;
      
        bool _navBarColorAnimated = false;
        Color _navBarColor = Colors.black;
        NavigationBarStyle _navBarStyle = NavigationBarStyle.DEFAULT;
      
        @override
        void initState() {
          super.initState();
          initPlatformState();
        }
      
        // Platform messages are asynchronous, so we initialize in an async method.
        Future<void> initPlatformState() async {
          double statusBarHeight;
          // Platform messages may fail, so we use a try/catch PlatformException.
          try {
            statusBarHeight = await FlutterStatusbarManager.getHeight;
          } on PlatformException {
            statusBarHeight = 0.0;
          }
          if (!mounted) return;
      
          setState(() {
            _statusBarHeight = statusBarHeight;
          });
        }
      
        Widget renderTitle(String text) {
          final textStyle = TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold);
          return Text(text, style: textStyle);
        }
      
        void colorBarChanged(Color val) {
          this.setState(() {
            _statusBarColor = val;
          });
          updateStatusBar();
        }
      
        void updateStatusBar() {
          FlutterStatusbarManager.setColor(
              _statusBarColor.withOpacity(_statusBarOpacity),
              animated: _statusBarColorAnimated);
        }
      
        void statusBarAnimationChanged(StatusBarAnimation val) {
          this.setState(() {
            _statusBarAnimation = val;
          });
        }
      
        void statusBarStyleChanged(StatusBarStyle val) {
          this.setState(() {
            _statusBarStyle = val;
          });
          FlutterStatusbarManager.setStyle(val);
        }
      
        void colorNavBarChanged(Color val) {
          this.setState(() {
            _navBarColor = val;
          });
          updateNavBar();
        }
      
        void updateNavBar() {
          FlutterStatusbarManager.setNavigationBarColor(_navBarColor,
              animated: _navBarColorAnimated);
        }
      
        void navigationBarStyleChanged(NavigationBarStyle val) {
          this.setState(() {
            _navBarStyle = val;
          });
          FlutterStatusbarManager.setNavigationBarStyle(val);
        }
      
        @override
        Widget build(BuildContext context) {
          return new MaterialApp(
            home: new Scaffold(
              appBar: new AppBar(
                title: const Text('Statusbar Manager example'),
              ),
              body: new Container(
                child: new Scrollbar(
                  child: new ListView(
                    padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
                    children: <Widget>[
                      renderTitle("Status Bar Height: $_statusBarHeight"),
                      Divider(height: 25.0),
                      renderTitle("Status Bar Color:"),
                      SwitchListTile(
                        value: _statusBarColorAnimated,
                        title: new Text("Animated:"),
                        onChanged: (bool value) {
                          this.setState(() {
                            _statusBarColorAnimated = value;
                          });
                        },
                      ),
                      Text("Color:"),
                      RadioListTile(
                          value: Colors.black,
                          title: Text("Black"),
                          onChanged: colorBarChanged,
                          dense: true,
                          groupValue: _statusBarColor),
                      RadioListTile(
                          value: Colors.orange,
                          title: Text("Orange"),
                          onChanged: colorBarChanged,
                          dense: true,
                          groupValue: _statusBarColor),
                      RadioListTile(
                          value: Colors.greenAccent,
                          title: Text("Green"),
                          onChanged: colorBarChanged,
                          dense: true,
                          groupValue: _statusBarColor),
                      RadioListTile(
                          value: Colors.white30,
                          title: Text("White"),
                          onChanged: colorBarChanged,
                          dense: true,
                          groupValue: _statusBarColor),
                      Text("Opacity:"),
                      Slider(
                        value: _statusBarOpacity,
                        min: 0.0,
                        max: 1.0,
                        onChanged: (double val) {
                          this.setState(() {
                            _statusBarOpacity = val;
                          });
                          updateStatusBar();
                        },
                      ),
                      Divider(height: 25.0),
                      renderTitle("Status Bar Hidden:"),
                      SwitchListTile(
                        title: new Text("Hidden:"),
                        value: _statusBarHidden,
                        onChanged: (bool val) {
                          this.setState(() {
                            _statusBarHidden = val;
                          });
                          FlutterStatusbarManager.setHidden(_statusBarHidden,
                              animation: _statusBarAnimation);
                        },
                      ),
                      Text("Animation:"),
                      RadioListTile(
                          value: StatusBarAnimation.NONE,
                          title: Text("NONE"),
                          onChanged: statusBarAnimationChanged,
                          dense: true,
                          groupValue: _statusBarAnimation),
                      RadioListTile(
                          value: StatusBarAnimation.FADE,
                          title: Text("FADE"),
                          onChanged: statusBarAnimationChanged,
                          dense: true,
                          groupValue: _statusBarAnimation),
                      RadioListTile(
                          value: StatusBarAnimation.SLIDE,
                          title: Text("SLIDE"),
                          onChanged: statusBarAnimationChanged,
                          dense: true,
                          groupValue: _statusBarAnimation),
                      Divider(height: 25.0),
                      renderTitle("Status Bar Style:"),
                      RadioListTile(
                          value: StatusBarStyle.DEFAULT,
                          title: Text("DEFAULT"),
                          onChanged: statusBarStyleChanged,
                          dense: true,
                          groupValue: _statusBarStyle),
                      RadioListTile(
                          value: StatusBarStyle.LIGHT_CONTENT,
                          title: Text("LIGHT_CONTENT"),
                          onChanged: statusBarStyleChanged,
                          dense: true,
                          groupValue: _statusBarStyle),
                      RadioListTile(
                          value: StatusBarStyle.DARK_CONTENT,
                          title: Text("DARK_CONTENT"),
                          onChanged: statusBarStyleChanged,
                          dense: true,
                          groupValue: _statusBarStyle),
                      Divider(height: 25.0),
                      renderTitle("Status Bar Translucent:"),
                      SwitchListTile(
                        title: new Text("Translucent:"),
                        value: _statusBarTranslucent,
                        onChanged: (bool val) {
                          this.setState(() {
                            _statusBarTranslucent = val;
                          });
                          FlutterStatusbarManager
                              .setTranslucent(_statusBarTranslucent);
                        },
                      ),
                      Divider(height: 25.0),
                      renderTitle("Status Bar Activity Indicator:"),
                      SwitchListTile(
                        title: new Text("Indicator:"),
                        value: _loadingIndicator,
                        onChanged: (bool val) {
                          this.setState(() {
                            _loadingIndicator = val;
                          });
                          FlutterStatusbarManager
                              .setNetworkActivityIndicatorVisible(_loadingIndicator);
                        },
                      ),
                      Divider(height: 25.0),
                      renderTitle("Navigation Bar Color:"),
                      SwitchListTile(
                        value: _navBarColorAnimated,
                        title: new Text("Animated:"),
                        onChanged: (bool value) {
                          this.setState(() {
                            _navBarColorAnimated = value;
                          });
                        },
                      ),
                      Text("Color:"),
                      RadioListTile(
                          value: Colors.black,
                          title: Text("Black"),
                          onChanged: colorNavBarChanged,
                          dense: true,
                          groupValue: _navBarColor),
                      RadioListTile(
                          value: Colors.orange,
                          title: Text("Orange"),
                          onChanged: colorNavBarChanged,
                          dense: true,
                          groupValue: _navBarColor),
                      RadioListTile(
                          value: Colors.greenAccent,
                          title: Text("Green"),
                          onChanged: colorNavBarChanged,
                          dense: true,
                          groupValue: _navBarColor),
                      RadioListTile(
                          value: Colors.white12,
                          title: Text("white"),
                          onChanged: colorNavBarChanged,
                          dense: true,
                          groupValue: _navBarColor),
                      Divider(height: 25.0),
                      renderTitle("Navigation Bar Style:"),
                      RadioListTile(
                          value: NavigationBarStyle.DEFAULT,
                          title: Text("DEFAULT"),
                          onChanged: navigationBarStyleChanged,
                          dense: true,
                          groupValue: _navBarStyle),
                      RadioListTile(
                          value: NavigationBarStyle.LIGHT,
                          title: Text("LIGHT"),
                          onChanged: navigationBarStyleChanged,
                          dense: true,
                          groupValue: _navBarStyle),
                      RadioListTile(
                          value: NavigationBarStyle.DARK,
                          title: Text("DARK"),
                          onChanged: navigationBarStyleChanged,
                          dense: true,
                          groupValue: _navBarStyle),
                      Divider(height: 25.0),
                      renderTitle("Fullscreen mode:"),
                      SwitchListTile(
                        title: new Text("Fullscreen:"),
                        value: _fullscreenMode,
                        onChanged: (bool val) {
                          this.setState(() {
                            _fullscreenMode = val;
                          });
                          FlutterStatusbarManager.setFullscreen(_fullscreenMode);
                        },
                      ),
                    ],
                  ),
                ),
              ),
            ),
          );
        }
      }
      

      【讨论】:

        【解决方案7】:

        如果您查看 AppBar 的 source code,您会发现它们使用了 AnnotatedRegion 小部件。 AnnotedRegion 小部件使您可以更好地控制系统覆盖样式。这是在不使用应用栏时配置系统样式的一种更灵活的方式。

        据我了解,当包裹在其中的小部件被状态栏/导航栏覆盖时,此小部件会自动设置状态栏/导航栏颜色。

        你可以像这样包装你的小部件:

        import 'package:flutter/services.dart';
        
        ...    
        
        Widget build(BuildContext context) {
           return Scaffold(
              body: AnnotatedRegion<SystemUiOverlayStyle>(
                 value: SystemUiOverlayStyle.light,                
                 child: ...,
              ),
           );
        }
        

        有关 AnnotatedRegion 小部件的更多信息,请访问API Docs

        【讨论】:

        • 这应该是公认的答案,因为它与框架处理它的方式一致
        • 同意 - 如果前一页使用不同的值,它还会处理页面转换
        • 另外,如果我有一个带有深色/浅色主题的应用程序,我会在值中使用此代码: (Theme.of(context).brightness == Brightness.dark) ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark
        • 替换这个来改变状态栏颜色value: SystemUiOverlayStyle.light.copyWith( statusBarColor: Theme.of(context).primaryColor, )
        • 应用似乎更落后于这种方法
        【解决方案8】:

        正如已经提到的解决方案,我正在以不同的方法实施它。遵循的方法是删除 AppBar 并使用 Container 小部件更改状态栏的颜色。

        void main() {
          runApp(
            MaterialApp(
              debugShowCheckedModeBanner: false,
              title: 'Test',
              home: Scaffold(
                primary: true,
                appBar: EmptyAppBar(),
                body: MyScaffold(),
              ),
            ),
          );
        }
        
        class MyScaffold extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return Container(
              child: Text(
                'Test',
              ),
            );
          }
        }
        
        class EmptyAppBar extends StatelessWidget implements PreferredSizeWidget {
          @override
          Widget build(BuildContext context) {
            return Container(
              color: Colors.black,
            );
          }
        
          @override
          Size get preferredSize => Size(0.0, 0.0);
        }
        
        • 这里我使用 EmptyAppBar 类来删除 AppBar,它默认存在于 Scaffold
        • EmptyAppBar 类中,我们可以在容器小部件中选择所需的颜色。
        • 之后,您就有了自己的自定义 MyScaffold 类来创建小部件。在我的代码中,我创建了一个文本。

        参考:GitHub Issue

        【讨论】:

        • 我发现这是结合屏幕(有和没有AppBar)的应用程序的最佳解决方案。 SystemUiOverlayStyle 方法会覆盖 AppBar 设置,并且在离开屏幕时不会重置。
        • 这是唯一对我有用的解决方案,谢谢
        【解决方案9】:

        你应该通过两种方式解决这个问题:

        1. 你没有设置appBar那么你就这样写:
        SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
          statusBarColor: Colors.black, 
        ));
        
        

        SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(
          statusBarColor: Colors.white, 
        ));
        
        1. 你总是设置 appBar,所以你应该设置 appBar 但不是在代码上:
        Scaffold(
          appBar: AppBar(
            brightness: Brightness.light,
          )
        )
        

        Scaffold(
          appBar: AppBar(
            brightness: Brightness.dark,
          )
        )
        

        【讨论】:

        • 谢谢...在我的情况下,当我将 SystemUiOverlayStyle.dark 与 statusBarColor: Colors.white 一起使用时它起作用了
        • 谢谢先生。 brightness: Brightness.dark 工作。
        • 解释得好,节省了很多时间。
        【解决方案10】:

        使用EmptyAppBar,以及一些用于恢复颜色的代码,如AppBar

        class EmptyAppBar  extends StatelessWidget implements PreferredSizeWidget {
          static const double _defaultElevation = 4.0;
          @override
          Widget build(BuildContext context) {
            final ThemeData themeData = Theme.of(context);
            final AppBarTheme appBarTheme = AppBarTheme.of(context);
            final Brightness brightness = appBarTheme.brightness
                ?? themeData.primaryColorBrightness;
            final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
                ? SystemUiOverlayStyle.light
                : SystemUiOverlayStyle.dark;
        
            return Semantics(
              container: true,
              child: AnnotatedRegion<SystemUiOverlayStyle>(
                value: overlayStyle,
                child: Material(
                  color: appBarTheme.color
                      ?? themeData.primaryColor,
                  elevation: appBarTheme.elevation
                      ?? _defaultElevation,
                  child: Semantics(
                    explicitChildNodes: true,
                    child: Container(),
                  ),
                ),
              ),
            );
          }
          @override
          Size get preferredSize => Size(0.0,0.0);
        }
        

        【讨论】:

          【解决方案11】:

          使用

          AppBar(
            systemOverlayStyle: SystemUiOverlayStyle(statusBarColor: Colors.orange),
          )
          

          AppBar(
            backgroundColor: Colors.red, // Status bar color
            brightness: Brightness.light, // Status bar brightness
          )
          

          【讨论】:

          • backwardsCompatibility 到底是做什么的?
          • @Stuck backwardsCompatibility 将在未来被删除,其默认值将设置为 false,我刚刚这样做了。设置它 true 不允许 systemOverlayStyle 属性工作。
          • 过时的落后比较
          • @petrasJ 是的,正如我之前在评论中提到的那样,它将被弃用。
          【解决方案12】:

          只需将此添加到您的构建函数或主函数中。

          import 'package:flutter/services.dart';
          
          Widget build(BuildContext context) {
            SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
            ...
          }
          

          【讨论】:

            【解决方案13】:

            这个最好的状态栏就像没有 AppBar() 的默认材料设计主题

             Container(width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).padding.top, color: Theme.of(context).accentColor)
            

            【讨论】:

            • 这只是完美的答案,对我帮助很大。每个视图可以有不同的状态栏颜色,我们不必担心为什么某些特定视图使用颜色,而实际上不需要。
            【解决方案14】:

            我尝试了很多方法,但都没有奏效。我找到了另一种方法,使用 safeArea ,AnnotatedRegion 和 Scaffold

            AnnotatedRegion(
              // status icon and text color, dark:black  light:white
              value: SystemUiOverlayStyle.dark,
              child: Scaffold(
                 // statusbar color
                 backgroundColor: Colors.white,
                 body : SafeArea(****)
              )
            }
            

            代码实现了白色状态栏和黑色文字

            【讨论】:

              【解决方案15】:

              如果您想在 MaterialApp 主题中用作默认模板,您只需添加它:

              appBarTheme: AppBarTheme(brightness: Brightness.light)
              

              结果会是这样的:

              return MaterialApp(
                    title: 'Flutter Demo',
                    theme: ThemeData(
                      primarySwatch: Colors.blue,
                      appBarTheme: AppBarTheme(brightness: Brightness.light),  <========
                      visualDensity: VisualDensity.adaptivePlatformDensity,
                    ),
                    home: ...,
                  );
              

              【讨论】:

                【解决方案16】:

                在您的主要功能中使用以下内容来更改所有视图/屏幕的状态栏颜色。即使没有应用栏也可以使用。

                WidgetsFlutterBinding.ensureInitialized();
                SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
                  statusBarIconBrightness: Brightness.dark, // this will change the brightness of the icons
                  statusBarColor: Colors.white, // or any color you want
                ));
                

                【讨论】:

                  【解决方案17】:

                  如果你不想使用应用栏,那么

                  appBar: AppBar(
                        elevation: 0,
                        backgroundColor: Colors.white, # status bar color
                        toolbarHeight: 0,
                        brightness: Brightness.light # or Brightness.dark
                  

                  【讨论】:

                    【解决方案18】:

                    您可以使用SystemUiOverlayStyle

                     Scaffold(
                              backgroundColor: Colors.white,
                              appBar: AppBar(
                                  backgroundColor: Colors.white,
                                  elevation: 0.0,
                                  systemOverlayStyle: SystemUiOverlayStyle(
                                    statusBarColor: Colors.white,
                                    statusBarBrightness: Brightness.dark,
                                    statusBarIconBrightness: Brightness.dark,
                                  )),
                              body:.....
                    

                    【讨论】:

                    • 这不再正常工作了
                    猜你喜欢
                    • 2019-12-22
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-06-04
                    • 2020-09-03
                    • 2023-03-05
                    • 2020-01-11
                    • 1970-01-01
                    • 2021-10-28
                    相关资源
                    最近更新 更多