Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flutter not automatically changing the status bar icons to black on devices running iOS 13.0 in Dark Mode it only does so when Dark Mode on iOS 13 is turned off #41067

Closed
Chimba123 opened this issue Sep 22, 2019 · 60 comments
Assignees
Labels
a: annoyance Repeatedly frustrating issues with non-experimental functionality customer: crowd Affects or could affect many people, though not necessarily a specific customer. engine flutter/engine repository. See also e: labels. f: cupertino flutter/packages/flutter/cupertino repository framework flutter/packages/flutter repository. See also f: labels. platform-ios iOS applications specifically

Comments

@Chimba123
Copy link

Chimba123 commented Sep 22, 2019

I upgraded my iPhone X operating system(OS) from 12.4 to iOS 13.0 and I also updated my Xcode to version 11. I have noticed one puzzling thing, previously when loading my Flutter app on my iPhone X running iOS 12.4 then the status bar icons(network, wifi, battery, time) would automatically turn black to provide contrast from the grey Cupertino Navigation Bar and white Material App Bar widgets. But when I upgraded the OS on the actual device this automatic functionality is gone and the status icons are white and barely visible. It only does so when Dark Mode on the device is turned off.

How could we get the automatic functionality of status bar icons and text switching to black in Dark Mode on iOS 13?

@Mugen0
Copy link

Mugen0 commented Sep 22, 2019

Turn off dark mode on your device and it will appear as before. Yet I don't know how to adapt if dark mode is on.

@Chimba123
Copy link
Author

Chimba123 commented Sep 22, 2019

@Mugen0 Thanks I actually lost my temper with it and yet such a simple fix

@Chimba123
Copy link
Author

Chimba123 commented Sep 22, 2019

@Mugen0 maybe you can open an issue for the Dark Mode.

@janmoppel janmoppel added a: images Loading, displaying, rendering images customer: crowd Affects or could affect many people, though not necessarily a specific customer. framework flutter/packages/flutter repository. See also f: labels. platform-ios iOS applications specifically labels Sep 23, 2019
@Chimba123 Chimba123 changed the title Flutter not automatically changing the status bar icons to black on an actual device(iPhone X) running iOS 13.0 it only does so on a virtual device Flutter not automatically changing the status bar icons to black on an devices running iOS 13.0 in Dark Mode it only does so when Dark Mode on iOS 13 is turned off Sep 23, 2019
@Chimba123 Chimba123 changed the title Flutter not automatically changing the status bar icons to black on an devices running iOS 13.0 in Dark Mode it only does so when Dark Mode on iOS 13 is turned off Flutter not automatically changing the status bar icons to black on a devices running iOS 13.0 in Dark Mode it only does so when Dark Mode on iOS 13 is turned off Sep 23, 2019
@cetorres
Copy link

Turning off dark mode on iOS 13 is not the solution. We should have a way to either detect dark mode and deal with the status bar color by ourselves or the framework could do it automatically. It should be an issue to be fixed.

@Chimba123 Chimba123 changed the title Flutter not automatically changing the status bar icons to black on a devices running iOS 13.0 in Dark Mode it only does so when Dark Mode on iOS 13 is turned off Flutter not automatically changing the status bar icons to black on devices running iOS 13.0 in Dark Mode it only does so when Dark Mode on iOS 13 is turned off Sep 23, 2019
@vanelizarov
Copy link
Contributor

Some time ago I've written a simple plugin for getting iOS 13 Dark Mode enabled state
Basically it can be a temporary workaround for this problem

@Chimba123
Copy link
Author

@vanelizarov could you please illustrate a comprehensive example on how to use your plugin?

@Mugen0
Copy link

Mugen0 commented Sep 28, 2019

@vanelizarov I got an error with the plugin.
fatal error: 'flutter_ios_dark_mode/flutter_ios_dark_mode-Swift.h' file not

@vanelizarov
Copy link
Contributor

@Mugen0 your app needs to be scaffolded with Swift language because plugin is written in Swift

@vanelizarov
Copy link
Contributor

vanelizarov commented Sep 29, 2019

@Chimba123 sorry for the false alarm, I've tried to write an example app and figured out that my plugin can help, but not exactly in the way I've expected. For example you can subscribe to onDarkModeStateChanged via StreamBuilder and change app brightness dynamically so the app's theme also changes to dark appearance. I know that it's not an accurate solution for our problem, but it's better than nothing. Here's the minimal runnable example:

import 'package:flutter/cupertino.dart';
import 'package:flutter_ios_dark_mode/flutter_ios_dark_mode.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<bool>(
      stream: FlutterIosDarkMode().onDarkModeStateChanged,
      initialData: false,
      builder: (context, snapshot) {
        return CupertinoApp(
          debugShowCheckedModeBanner: false,
          theme: CupertinoThemeData(
            brightness: snapshot.data ? Brightness.dark : Brightness.light,
          ),
          home: Home(),
        );
      },
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(),
      child: Container(),
    );
  }
}

Unfortunately, if you set barBackgroundColor strictly to let's say white and then switch to dark mode - status bar items color stays white, even with the help of this plugin. So, the most correct solution I think will be to wait for Flutter team to fix this problem or try to fix it on our own

@Piinks Piinks added the f: cupertino flutter/packages/flutter/cupertino repository label Sep 30, 2019
@LongCatIsLooong
Copy link
Contributor

LongCatIsLooong commented Oct 3, 2019

On Xcode 11.2 beta & iOS 13.2, setting UIApplicatin.shared.statusBarStyle (which is also deprecated) seems to have stopped working. UIViewController.preferredStatusBarStyle works fine.
Didn't check info.plist. Will try again on Monday.

@LongCatIsLooong LongCatIsLooong added engine flutter/engine repository. See also e: labels. and removed a: images Loading, displaying, rendering images labels Oct 4, 2019
@LongCatIsLooong LongCatIsLooong self-assigned this Oct 4, 2019
@01xJoao
Copy link

01xJoao commented Oct 9, 2019

Any news on this ?

@blackox626
Copy link

FlutterPlatformPlugin

- (void)setSystemChromeSystemUIOverlayStyle:(NSDictionary*)message {
  NSString* style = message[@"statusBarBrightness"];
  if (style == (id)[NSNull null])
    return;

  UIStatusBarStyle statusBarStyle;
  if ([style isEqualToString:@"Brightness.dark"])
    statusBarStyle = UIStatusBarStyleLightContent;
  else if ([style isEqualToString:@"Brightness.light"])
    statusBarStyle = UIStatusBarStyleDefault;
  else
    return;

  NSNumber* infoValue = [[NSBundle mainBundle]
      objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"];
  Boolean delegateToViewController = (infoValue == nil || [infoValue boolValue]);

  if (delegateToViewController) {
    // This notification is respected by the iOS embedder
    [[NSNotificationCenter defaultCenter]
        postNotificationName:@(kOverlayStyleUpdateNotificationName)
                      object:nil
                    userInfo:@{@(kOverlayStyleUpdateNotificationKey) : @(statusBarStyle)}];
  } else {
    // Note: -[UIApplication setStatusBarStyle] is deprecated in iOS9
    // in favor of delegating to the view controller
    [[UIApplication sharedApplication] setStatusBarStyle:statusBarStyle];
  }
}

engine code ,we can see no UIStatusBarStyleDarkContent

delete ‘UIViewControllerBasedStatusBarAppearance ’ from info.plist

add notification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appStatusBar:) name:@"io.flutter.plugin.platform.SystemChromeOverlayNotificationName" object:nil];

- (void)appStatusBar:(id)notification {
    if (@available(iOS 13.0, *)) {
        [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDarkContent;
    }
}

@jayjun
Copy link
Contributor

jayjun commented Oct 14, 2019

The problem is SystemUiOverlayStyle.dark sets the status bar style as UIStatusBarStyleDefault, which defaults to light text in Dark Mode.

I sent flutter/engine#13119 to use UIStatusBarStyleDarkContent (iOS 13.0+) instead, which should fix this issue.

@Chimba123
Copy link
Author

@jayjun keep us posted

@vanelizarov
Copy link
Contributor

vanelizarov commented Oct 14, 2019

@blackox626 thanks for the idea, I've finally figured out how to temporarily fix this issue via native code, while we all are waiting for @jayjun's PR to be merged

  1. Set View controller based status bar appearance in Info.plist to YES
    1.1. (Optional) Set Status bar style option to whatever value you want to determine status bar color on app start

Screen Shot 2019-10-14 at 15 05 57

  1. Add this extension for FlutterViewController to separate file or below the AppDelegate:
let kOverlayStyleUpdateNotificationName = "io.flutter.plugin.platform.SystemChromeOverlayNotificationName"
let kOverlayStyleUpdateNotificationKey = "io.flutter.plugin.platform.SystemChromeOverlayNotificationKey"

extension FlutterViewController {
    private struct StatusBarStyleHolder {
        static var style: UIStatusBarStyle = .default
    }
    
    open override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(appStatusBar(notification:)),
            name: NSNotification.Name(kOverlayStyleUpdateNotificationName),
            object: nil
        )
    }

    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return StatusBarStyleHolder.style
    }
    
    @objc private func appStatusBar(notification: NSNotification) {
        guard
            let info = notification.userInfo as? Dictionary<String, Any>,
            let statusBarStyleKey = info[kOverlayStyleUpdateNotificationKey] as? Int
        else {
            return
        }
        
        if #available(iOS 13.0, *) {
            StatusBarStyleHolder.style = statusBarStyleKey == 0 ? .darkContent : .lightContent
        } else {
            StatusBarStyleHolder.style = statusBarStyleKey == 0 ? .default : .lightContent
        }
        
        setNeedsStatusBarAppearanceUpdate()
    }
}

@ZacharyEilers
Copy link

Same. Still waiting for fix.

@atereshkov
Copy link

Hm, almost 4 months of waiting..

@dotcink
Copy link

dotcink commented Jan 6, 2020

@blackox626 thanks for the idea, I've finally figured out how to temporarily fix this issue via native code, while we all are waiting for @jayjun's PR to be merged

  1. Set View controller based status bar appearance in Info.plist to YES
    1.1. (Optional) Set Status bar style option to whatever value you want to determine status bar color on app start
Screen Shot 2019-10-14 at 15 05 57
  1. Add this extension for FlutterViewController to separate file or below the AppDelegate:
let kOverlayStyleUpdateNotificationName = "io.flutter.plugin.platform.SystemChromeOverlayNotificationName"
let kOverlayStyleUpdateNotificationKey = "io.flutter.plugin.platform.SystemChromeOverlayNotificationKey"

extension FlutterViewController {
    private struct StatusBarStyleHolder {
        static var style: UIStatusBarStyle = .default
    }
    
    open override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(appStatusBar(notification:)),
            name: NSNotification.Name(kOverlayStyleUpdateNotificationName),
            object: nil
        )
    }

    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return StatusBarStyleHolder.style
    }
    
    @objc private func appStatusBar(notification: NSNotification) {
        guard
            let info = notification.userInfo as? Dictionary<String, Any>,
            let statusBarStyleKey = info[kOverlayStyleUpdateNotificationKey] as? Int
        else {
            return
        }
        
        if #available(iOS 13.0, *) {
            StatusBarStyleHolder.style = statusBarStyleKey == 0 ? .darkContent : .lightContent
        } else {
            StatusBarStyleHolder.style = statusBarStyleKey == 0 ? .default : .lightContent
        }
        
        setNeedsStatusBarAppearanceUpdate()
    }
}

This solves the status bar color problem, but results in another.
I cannot hide the status bar with SystemChrome.setEnabledSystemUIOverlays([]);.

@luscas
Copy link

luscas commented Jan 7, 2020

Add line in Info.plist

<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

And change status bar 👍

import 'package:flutter/services.dart';
/// ...
SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(statusBarBrightness: Brightness.light) // Or Brightness.dark
);

@330676687
Copy link

Add line in Info.plist

<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

And change status bar 👍

import 'package:flutter/services.dart';
/// ...
SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(statusBarBrightness: Brightness.light) // Or Brightness.dark
);

nice!!!

@Csutkas
Copy link

Csutkas commented Jan 10, 2020

Thank you!

For beginners like me:
Info.plist is under ios/Runner

@shorben07
Copy link

One more possible workaround:

  1. Set View controller-based status bar appearance in Info.plist to YES
  2. Create a subclass of the flutter view controller
class CustomFlutterViewController: FlutterViewController {
    
    override open var preferredStatusBarStyle: UIStatusBarStyle {
        let value = super.preferredStatusBarStyle
        if #available(iOS 13.0, *) {
            return value == .default ? .darkContent : value
        } else {
            return value
        }
    }
} 

@gabryelferreira
Copy link

@330676687 Works like a charm. Tks!

@LongCatIsLooong
Copy link
Contributor

Seems to be working on master now. Closing.

@edwardez
Copy link

Will a hotfix be issued on 1.12.13 for this fix? Or this won’t be merged to stable until next major release?

@LongCatIsLooong
Copy link
Contributor

@edwardez not that I know of. To quote the wiki:

Will a particular bug fix be provided in a hotfix release?
Almost certainly not. We only hotfix the most egregious bugs (e.g. "nobody can build on iOS any more"), and even then we're more likely to just release a new build.

If you really need a particular patch and it's a fix to the flutter/flutter repository, you should feel free to create a Flutter branch yourself on your development machine and cherry-pick the fix you want onto that branch. Flutter is distributed as a git repository and all of git's tools are available to you. If you need a particular patch that's from the flutter/engine repository or one of our dependencies (e.g. Dart or Skia), you could build your own engine but it's probably easier to just wait until the next release. On average, the next dev release is about a day away and the next beta release is about two weeks away.

Switching to the dev channel or the beta channel could also be an option.

@edwardez
Copy link

edwardez commented Jan 16, 2020

@edwardez not that I know of. To quote the wiki:

Will a particular bug fix be provided in a hotfix release?
Almost certainly not. We only hotfix the most egregious bugs (e.g. "nobody can build on iOS any more"), and even then we're more likely to just release a new build.
If you really need a particular patch and it's a fix to the flutter/flutter repository, you should feel free to create a Flutter branch yourself on your development machine and cherry-pick the fix you want onto that branch. Flutter is distributed as a git repository and all of git's tools are available to you. If you need a particular patch that's from the flutter/engine repository or one of our dependencies (e.g. Dart or Skia), you could build your own engine but it's probably easier to just wait until the next release. On average, the next dev release is about a day away and the next beta release is about two weeks away.

Switching to the dev channel or the beta channel could also be an option.

Make sense, I was thinking this issue has lots of votes and might be merged to stable as an exception...thanks for the detailed explanation.

@mono0926
Copy link
Contributor

Seems to be working on master now. Closing.

Fixed by flutter/engine#13119

@Chimba123
Copy link
Author

@mono0926 is it safe for us to use the Master Channel in production? Our concern is a production ready solution, not a developer-only solution.

@Chimba123
Copy link
Author

@mono0926 if we can't use the master channel to deploy our final Apps to the App store as a well-finished product then I'd advise you to re-open the issue till it is properly addressed on the stable channel

@BassamxMednini
Copy link

It works fine in the simulator, but on a real device it doesn't work...

@atereshkov
Copy link

My app freezes when I run Flutter from master channel. I had to switch to stable version where's no fix exists for this issue. News, guys?

@minikin
Copy link

minikin commented Feb 12, 2020

btw: @eugene-kalaganov It's a bad practice to fully rely on how things work in a simulator (iOS).

@woutergoossens
Copy link

How can we have this fix in our apps?

@LongCatIsLooong
Copy link
Contributor

@atereshkov could you create a new issue, if there isn't one already? That sounds like a severe problem.

also the dev channel and the beta channel should have the fix now if you don't want to patch and build the engine manually.

@filiph filiph added the a: annoyance Repeatedly frustrating issues with non-experimental functionality label Feb 19, 2020
@ilweonair
Copy link

@atereshkov are there any news about this issue? Could you create a new issue?

@atereshkov
Copy link

atereshkov commented Feb 24, 2020

@ilweonair I'll check it one more time today and will address if it's still an issue

@nilsreichardt
Copy link
Contributor

For me this issue is fixed in flutter beta and everything is working fine 👍

@ilweonair
Copy link

ilweonair commented Feb 25, 2020 via email

@lukepighetti
Copy link

@ilweonair Depends on your pipelining needs. We typically deploy from dev

@diepnguyen137
Copy link

Add line in Info.plist

<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

And change status bar 👍

import 'package:flutter/services.dart';
/// ...
SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(statusBarBrightness: Brightness.light) // Or Brightness.dark
);

work like charm <3

@lock
Copy link

lock bot commented Apr 4, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@lock lock bot locked and limited conversation to collaborators Apr 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: annoyance Repeatedly frustrating issues with non-experimental functionality customer: crowd Affects or could affect many people, though not necessarily a specific customer. engine flutter/engine repository. See also e: labels. f: cupertino flutter/packages/flutter/cupertino repository framework flutter/packages/flutter repository. See also f: labels. platform-ios iOS applications specifically
Projects
None yet
Development

No branches or pull requests