Tsubasa
Tsubasa

Reputation: 541

Flutter: Where should I call SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark)

In my flutter app, screen A has no AppBar. So I call SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark) in build.

After another screen B which has an AppBar was pushed and then popped, screen A has light status bar.

I'd like the system UI to return to the original setting when the screen is popped.

Gif

Upvotes: 26

Views: 23894

Answers (6)

Sardor Bek
Sardor Bek

Reputation: 1

Future.delayed(Duration(milliseconds: 300)).then((value) => SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark));

i found that you can acctually do that in stateless widget's build method and it works like nothing happened

Upvotes: 0

Babag3ldi
Babag3ldi

Reputation: 31

Add this to the main screen:

void main() {
 
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarIconBrightness: Brightness.light,
  ));
  runApp(const MyApp());
}

Upvotes: 1

phoenix
phoenix

Reputation: 401

maybe you can wrap the whole page widget with AnnotatedRegion like this:

AnnotatedRegion(
value: _currentStyle,
child: Center(
  child: ElevatedButton(
    child: const Text('Change Color'),
    onPressed: _changeColor,
   ),
 ),
);

you can follow the full example here: https://api.flutter.dev/flutter/services/SystemChrome/setSystemUIOverlayStyle.html

Upvotes: 7

Angelica
Angelica

Reputation: 478

Add this package to your project Need Resume and extends your screen state to ResumableState

import 'package:need_resume/need_resume.dart';

class WelcomeScreen extends StatefulWidget {
  final String title;

  const WelcomeScreen({Key key, this.title}) : super(key: key);
  @override
  _WelcomeScreenState createState() => _WelcomeScreenState();
}

class _WelcomeScreenState extends ResumableState<WelcomeScreen> {
  @override
  void onResume() {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
    super.onResume();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [],
      ),
    );
  }
}

This solutions works as expected with very little changes in the code.

Upvotes: 0

Thales Albert0
Thales Albert0

Reputation: 101

maybe that works

SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.transparent)

Upvotes: 0

Miguel Ruivo
Miguel Ruivo

Reputation: 17756

The reason behind this is the fact that your new screen will have its own lifecycle and thus, might use another color for the status bar.

You can call SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark) in your initState method but that won't trigger after a stacked screen is popped. There are two problems here, you can, however, call that back again after returning from a screen pop(). Simple enough right? Almost there.

When you press the back button on the AppBar widget, will return immediately from your Navigator.of(context).push(someroute), even if the navigation animation is still being rendered from the stacked screen. To handle this, you can add a little "tweak" that will set the status bar color again after 500 milseconds, that should be enough for the animation to fully complete. So, you'll want something more or less like this:

class HomeScreen extends StatefulWidget {
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    _updateAppbar();
    super.initState();
  }

  void _updateAppbar() {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: RaisedButton(
            child: Text('Navigate to second screen'),
            onPressed: () => Navigator.of(context)
                .push(MaterialPageRoute(builder: (BuildContext context) => SecondScreen()))
                .whenComplete(() => Future.delayed(Duration(milliseconds: 500)).then((_) => _updateAppbar()))));
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
    );
  }
}

Although this works, I'm still curious to know if someone knows a better way to handle this though and keep a status bar color binding to each screen.

Upvotes: 10

Related Questions