-
Notifications
You must be signed in to change notification settings - Fork 6k
[ios] view controller based status bar #42643
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,11 +30,21 @@ | |
| "io.flutter.plugin.platform.SystemChromeOverlayNotificationName"; | ||
| const char* const kOverlayStyleUpdateNotificationKey = | ||
| "io.flutter.plugin.platform.SystemChromeOverlayNotificationKey"; | ||
| const char* const kStatusBarHiddenUpdateNotificationName = | ||
| "io.flutter.plugin.platform.StatusBarHiddenNotificationName"; | ||
| const char* const kStatusBarHiddenUpdateNotificationKey = | ||
| "io.flutter.plugin.platform.StatusBarHiddenNotificationKey"; | ||
|
|
||
| } // namespace flutter | ||
|
|
||
| using namespace flutter; | ||
|
|
||
| @interface FlutterPlatformPlugin () | ||
|
|
||
| @property(nonatomic, assign) BOOL enableViewControllerBasedStatusBarAppearance; | ||
|
|
||
| @end | ||
|
|
||
| @implementation FlutterPlatformPlugin { | ||
| fml::WeakPtr<FlutterEngine> _engine; | ||
| // Used to detect whether this device has live text input ability or not. | ||
|
|
@@ -47,6 +57,9 @@ - (instancetype)initWithEngine:(fml::WeakPtr<FlutterEngine>)engine { | |
|
|
||
| if (self) { | ||
| _engine = engine; | ||
| NSNumber* infoValue = [[NSBundle mainBundle] | ||
|
||
| objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"]; | ||
| _enableViewControllerBasedStatusBarAppearance = (infoValue == nil || [infoValue boolValue]); | ||
stuartmorgan-g marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return self; | ||
|
|
@@ -158,14 +171,7 @@ - (void)setSystemChromeApplicationSwitcherDescription:(NSDictionary*)object { | |
| } | ||
|
|
||
| - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays { | ||
| // Checks if the top status bar should be visible. This platform ignores all | ||
| // other overlays | ||
|
|
||
| // We opt out of view controller based status bar visibility since we want | ||
| // to be able to modify this on the fly. The key used is | ||
| // UIViewControllerBasedStatusBarAppearance | ||
| [UIApplication sharedApplication].statusBarHidden = | ||
| ![overlays containsObject:@"SystemUiOverlay.top"]; | ||
| BOOL statusBarShouldBeHidden = ![overlays containsObject:@"SystemUiOverlay.top"]; | ||
| if ([overlays containsObject:@"SystemUiOverlay.bottom"]) { | ||
| [[NSNotificationCenter defaultCenter] | ||
| postNotificationName:FlutterViewControllerShowHomeIndicator | ||
|
|
@@ -175,26 +181,46 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays { | |
| postNotificationName:FlutterViewControllerHideHomeIndicator | ||
| object:nil]; | ||
| } | ||
| if (self.enableViewControllerBasedStatusBarAppearance) { | ||
| // This notification is respected by the iOS embedder | ||
|
||
| [[NSNotificationCenter defaultCenter] | ||
| postNotificationName:@(kStatusBarHiddenUpdateNotificationName) | ||
| object:nil | ||
| userInfo:@{ | ||
| @(kStatusBarHiddenUpdateNotificationKey) : @(statusBarShouldBeHidden) | ||
| }]; | ||
| } else { | ||
| // Checks if the top status bar should be visible. This platform ignores all | ||
| // other overlays | ||
|
|
||
| // We opt out of view controller based status bar visibility since we want | ||
| // to be able to modify this on the fly. The key used is | ||
| // UIViewControllerBasedStatusBarAppearance | ||
| [UIApplication sharedApplication].statusBarHidden = statusBarShouldBeHidden; | ||
| } | ||
| } | ||
|
|
||
| - (void)setSystemChromeEnabledSystemUIMode:(NSString*)mode { | ||
| // Checks if the top status bar should be visible, reflected by edge to edge setting. This | ||
| // platform ignores all other system ui modes. | ||
|
|
||
| // We opt out of view controller based status bar visibility since we want | ||
| // to be able to modify this on the fly. The key used is | ||
| // UIViewControllerBasedStatusBarAppearance | ||
| [UIApplication sharedApplication].statusBarHidden = | ||
| ![mode isEqualToString:@"SystemUiMode.edgeToEdge"]; | ||
| if ([mode isEqualToString:@"SystemUiMode.edgeToEdge"]) { | ||
| BOOL edgeToEdge = [mode isEqualToString:@"SystemUiMode.edgeToEdge"]; | ||
| if (self.enableViewControllerBasedStatusBarAppearance) { | ||
| // This notification is respected by the iOS embedder | ||
| [[NSNotificationCenter defaultCenter] | ||
| postNotificationName:FlutterViewControllerShowHomeIndicator | ||
| object:nil]; | ||
| postNotificationName:@(kStatusBarHiddenUpdateNotificationName) | ||
| object:nil | ||
| userInfo:@{@(kStatusBarHiddenUpdateNotificationKey) : @(!edgeToEdge)}]; | ||
| } else { | ||
| [[NSNotificationCenter defaultCenter] | ||
| postNotificationName:FlutterViewControllerHideHomeIndicator | ||
| object:nil]; | ||
| // Checks if the top status bar should be visible, reflected by edge to edge setting. This | ||
| // platform ignores all other system ui modes. | ||
|
|
||
| // We opt out of view controller based status bar visibility since we want | ||
| // to be able to modify this on the fly. The key used is | ||
| // UIViewControllerBasedStatusBarAppearance | ||
| [UIApplication sharedApplication].statusBarHidden = !edgeToEdge; | ||
| } | ||
| [[NSNotificationCenter defaultCenter] | ||
| postNotificationName:edgeToEdge ? FlutterViewControllerShowHomeIndicator | ||
| : FlutterViewControllerHideHomeIndicator | ||
| object:nil]; | ||
| } | ||
|
|
||
| - (void)restoreSystemChromeSystemUIOverlays { | ||
|
|
@@ -220,11 +246,7 @@ - (void)setSystemChromeSystemUIOverlayStyle:(NSDictionary*)message { | |
| return; | ||
| } | ||
|
|
||
| NSNumber* infoValue = [[NSBundle mainBundle] | ||
| objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"]; | ||
| Boolean delegateToViewController = (infoValue == nil || [infoValue boolValue]); | ||
|
|
||
| if (delegateToViewController) { | ||
| if (self.enableViewControllerBasedStatusBarAppearance) { | ||
| // This notification is respected by the iOS embedder | ||
| [[NSNotificationCenter defaultCenter] | ||
| postNotificationName:@(kOverlayStyleUpdateNotificationName) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,6 +103,13 @@ @interface FlutterViewController () <FlutterBinaryMessenger, UIScrollViewDelegat | |
| @property(nonatomic, retain) | ||
| UIRotationGestureRecognizer* rotationGestureRecognizer API_AVAILABLE(ios(13.4)); | ||
|
|
||
| // Whether the status bar is prefered hidden. | ||
| // | ||
| // The |UIViewController:prefersStatusBarHidden| of this ViewController is overriden and returns | ||
| // `flutterPreferesStatusBarHidden`. Only works when `UIViewControllerBasedStatusBarAppearance` in | ||
| // info.plist of the app project is `true`. | ||
| @property(nonatomic, assign) BOOL flutterPreferesStatusBarHidden; | ||
|
||
|
|
||
| /** | ||
| * Creates and registers plugins used by this view controller. | ||
| */ | ||
|
|
@@ -299,6 +306,10 @@ - (void)setupNotificationCenterObservers { | |
| selector:@selector(onPreferredStatusBarStyleUpdated:) | ||
| name:@(flutter::kOverlayStyleUpdateNotificationName) | ||
| object:nil]; | ||
| [center addObserver:self | ||
| selector:@selector(onPreferredStatusBarHiddenUpdated:) | ||
| name:@(flutter::kStatusBarHiddenUpdateNotificationName) | ||
| object:nil]; | ||
|
|
||
| [center addObserver:self | ||
| selector:@selector(applicationBecameActive:) | ||
|
|
@@ -2081,6 +2092,31 @@ - (void)onPreferredStatusBarStyleUpdated:(NSNotification*)notification { | |
| }); | ||
| } | ||
|
|
||
| - (void)onPreferredStatusBarHiddenUpdated:(NSNotification*)notification { | ||
| FML_DCHECK( | ||
| [notification.name isEqualToString:@(flutter::kStatusBarHiddenUpdateNotificationName)]); | ||
| // Notifications may not be on the iOS UI thread | ||
| fml::TaskRunner::RunNowOrPostTask([_engine.get() platformTaskRunner], [&]() { | ||
| NSDictionary* info = notification.userInfo; | ||
|
|
||
| NSNumber* update = info[@(flutter::kStatusBarHiddenUpdateNotificationKey)]; | ||
|
|
||
| if (update == nil) { | ||
| return; | ||
| } | ||
|
|
||
| BOOL hidden = [update boolValue]; | ||
| if (hidden != self.flutterPreferesStatusBarHidden) { | ||
| self.flutterPreferesStatusBarHidden = hidden; | ||
| [self setNeedsStatusBarAppearanceUpdate]; | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| - (BOOL)prefersStatusBarHidden { | ||
| return self.flutterPreferesStatusBarHidden; | ||
| } | ||
|
|
||
| #pragma mark - Platform views | ||
|
|
||
| - (std::shared_ptr<flutter::FlutterPlatformViewsController>&)platformViewsController { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.