15

I am trying to add SafeArea widget for the flutter app with colorized system bars but somehow they are always turning black.

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

This is what I see enter image description here

If I wrap SafeArea inside a Container with color property set to white, it works but system bar icons also turn white enter image description here

Harshad Kale
  • 17,446
  • 7
  • 30
  • 44

6 Answers6

14

Building on @david-carrilho's answer, I created this simple widget

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

Then wherever I would use a SafeArea, I use my little wrapper widget 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'),
      ),
    );
  }
}

The reason why this works is because it creates a container behind your content with the specified color, then SafeArea simply adds the necessary padding based on the device.

davidcv5
  • 1,027
  • 8
  • 13
6

I know this is an old question, but after reading the documentation I came up with a more complete solution.

My answer considers the following:

  1. Don't wrap Scaffolds into SafeAreas;
  2. [iOS] paint your Scaffold the right Color;
  3. [Android] set the System Bars programmatically.

1. Proper use of SafeArea

SafeArea is a widget that performs a MediaQuery to add some proper padding to your application. This should happen inside the body of your Scaffold application. Something like this will lead to code that won't unexpectedly break later on:

return Scaffold(
  // ...
  body: SafeArea(                // your SafeArea should stay here
    child: YourWidget(),
  ),
);

2. iOS Notch

As other answers said already, you just have to paint your Scaffold so that you'll get the color you want. Your Scaffold should include a backgroundColor property (and your AppBar too, if you have one).

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

3. Android SystemUI

As OP did, you need SystemChrome.setSystemUIOverlayStyle() to address Android-related system bar paints.

However, the documentation says that this method should be called programmatically whenever a new page / a new route is being popped or pushed, if you have different Route colors.

Suppose you have a 2.0 Router; then, you would write its build method as it follows:

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

This will ensure that every time a new page is popped or pushed, i.e. the build method of our Router is called, the Android system bar and status bar are properly painted.

Dharman
  • 30,962
  • 25
  • 85
  • 135
venir
  • 1,809
  • 7
  • 19
4
Container(
   color ...
      ),
      child: SafeArea(
        child: Scaffold(
          body: 
            AnnotatedRegion<SystemUiOverlayStyle>(
               value: SystemUiOverlayStyle.light,
               child: ...
Steve Kim
  • 5,293
  • 16
  • 54
  • 99
  • 11
    Welcome to stackoverflow. In addition to the answer you've provided, please consider providing a brief explanation of why and how this fixes the issue. – jtate Jan 14 '20 at 22:06
  • 2
    I downvoted this. Don't use this solution, `SafeArea`s should ALWAYS be inside the Scaffold. This leads to having the navigation and the system bars being black for no reason. – venir Feb 21 '22 at 18:43
3

Replace your Overlay style with below code it will work

SystemChrome.setSystemUIOverlayStyle(
  SystemUiOverlayStyle.dark.copyWith(statusBarColor: Colors.white));
Jashwanth Neela
  • 263
  • 1
  • 8
  • 1
    underrated, used this with a slight adjustment (Colors.transparent) and it does the trick. – Jax297 Jun 28 '23 at 04:49
1

For your case just wrapping SafeArea() to the top widget that will be DISPLAYED on the screen(example: your 'Today' text widget) should avoid the black color on system bar.

Full example.

Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            SafeArea(
              child: Text('Today'),
            ),
            Text('Tomorrow')
          ]
      );

This worked for me!

abrsh
  • 454
  • 1
  • 6
  • 14
0

set only main class

  SystemChrome.setSystemUIOverlayStyle(
          SystemUiOverlayStyle.light.copyWith(
            systemNavigationBarIconBrightness: Brightness.dark,
            systemNavigationBarColor: Colors.white,
            statusBarIconBrightness: Brightness.light,
            statusBarColor: HexColor(HexColor.primarycolor), // Note RED here
          ),
        );  

  

my Example code

import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:loader_overlay/loader_overlay.dart';
    
    
    import 'HexColor.dart';
    
    class CityListActiviy extends StatefulWidget {
      // Initially password is obscure
      @override
      State<CityListActiviy> createState() => _CityListActiviyState();
    }
    
    class _CityListActiviyState extends State<CityListActiviy> {
      TextEditingController userid_Controller = new TextEditingController();
      bool userid_validate = false;
    
      final String requiredNumber = '123456';
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        SystemChrome.setSystemUIOverlayStyle(
          SystemUiOverlayStyle.light.copyWith(
            systemNavigationBarIconBrightness: Brightness.dark,
            systemNavigationBarColor: Colors.white,
            statusBarIconBrightness: Brightness.light,
            statusBarColor: HexColor(HexColor.primarycolor), // Note RED here
          ),
        );
    
        return MaterialApp(
          debugShowCheckedModeBanner: true,
          home: LoaderOverlay(
            child:SafeArea(
            child: Scaffold(
                backgroundColor: HexColor(HexColor.gray_activity_background),
                body: SingleChildScrollView(
                  child: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
    
                        Stack(
                          children: [
                            Container(
                                height: 60,
                                padding: new EdgeInsets.all(20.0),
                                decoration: BoxDecoration(
                                  color: HexColor(HexColor.white),
                                ),
                                width: MediaQuery.of(context).size.width,
                                child: Text("Select Your Location",
                                    textAlign: TextAlign.center,
                                    style: TextStyle(
                                      fontSize: 16,
                                      color: Colors.grey,
                                      fontFamily: 'montserrat_medium',
                                      decoration: TextDecoration.none,
                                    ))),
    
                          ],
                        )
                      ]),
                )),
            )
          ),
        );
      }
    }
sarjeet singh
  • 461
  • 4
  • 10