Flutter - AppBar 不存在时如何设置状态栏颜色

Flutter - How to set status bar color when AppBar not present

A​​ppBar 不存在时如何设置状态栏颜色。

我已经试过了,但没有用。

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();
             }
           },
        ),
       ),
    );
}

输出如下所示:

状态栏颜色由Android系统渲染。这是否可以从 Flutter 中设置还有待讨论:

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

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

实际上有两个 Dart 库,一个用于设置 light/dark theme of the statusbar and the other for setting the colour。我也没用过,但很明显其他人也遇到了你面临的同样问题并最终开发了他们自己的软件包。

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

getWindow().setStatusBarColor(0x00000000);

或者您可以使用 flutter_statusbarcolor 插件

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

Sample project

首先,导入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

在搜索 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

的信息
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();
             }
           },
        ),
       ),
      ),
    );
}

这里可以使用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);
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

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

据我了解,当包含在其中的小部件被 statusbar/navigationbar 覆盖时,此小部件会自动设置 statusbar/navigationbar 颜色。

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

import 'package:flutter/services.dart';

...    

Widget build(BuildContext context) {
   return Scaffold(
      body: AnnotatedRegion<SystemUiOverlayStyle>(
         value: SystemUiOverlayStyle.light,                
         child: ...,
      ),
   );
}

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

由于已经提到了解决方案,我正在以不同的方式实施它。接下来的方法是删除 A​​ppBar 并使用 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 class 删除 A​​ppBar 默认情况下出现在 脚手架
  • EmptyAppBarclass我们可以在容器widget中选择需要的颜色
  • 之后,您可以使用自己的自定义 MyScaffold class 来创建小部件。在我的代码中,我创建了一个文本。

参考:GitHub Issue

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

  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,
  )
)

使用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);
}

使用

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

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

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

import 'package:flutter/services.dart';

Widget build(BuildContext context) {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
  ...
}

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

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

我试了很多方法都没有用。我找到了另一种方法,使用 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(****)
  )
}

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

如果您想在 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: ...,
    );

在您的主函数中使用以下代码更改所有 views/screens 的状态栏颜色。即使没有应用栏也可以使用。

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
));

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

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

您可以使用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:.....