hvkale
hvkale

Reputation: 17787

Flutter - System bar colors with SafeArea

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

Upvotes: 18

Views: 21358

Answers (6)

sarjeet singh
sarjeet singh

Reputation: 541

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

Upvotes: 0

venir
venir

Reputation: 2097

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.

Upvotes: 9

Jashwanth Neela
Jashwanth Neela

Reputation: 463

Replace your Overlay style with below code it will work

SystemChrome.setSystemUIOverlayStyle(
  SystemUiOverlayStyle.dark.copyWith(statusBarColor: Colors.white));

Upvotes: 3

abrsh
abrsh

Reputation: 525

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!

Upvotes: 1

davidcv5
davidcv5

Reputation: 1167

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.

Upvotes: 16

David Carrilho
David Carrilho

Reputation: 55

Container(
   color ...
      ),
      child: SafeArea(
        child: Scaffold(
          body: 
            AnnotatedRegion<SystemUiOverlayStyle>(
               value: SystemUiOverlayStyle.light,
               child: ...

Upvotes: 3

Related Questions