Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1c6934e

Browse files
authored
Enabled hiding the home indicator with SystemChrome.setEnabledSystemUIOverlays (#17574)
1 parent 916f014 commit 1c6934e

File tree

6 files changed

+88
-25
lines changed

6 files changed

+88
-25
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrell
873873
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h
874874
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterView.mm
875875
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm
876-
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m
876+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm
877877
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h
878878
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h
879879
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm

shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
66
#include "flutter/fml/logging.h"
7+
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
78

89
#include <AudioToolbox/AudioToolbox.h>
910
#include <Foundation/Foundation.h>
@@ -161,6 +162,15 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays {
161162
// UIViewControllerBasedStatusBarAppearance
162163
[UIApplication sharedApplication].statusBarHidden =
163164
![overlays containsObject:@"SystemUiOverlay.top"];
165+
if ([overlays containsObject:@"SystemUiOverlay.bottom"]) {
166+
[[NSNotificationCenter defaultCenter]
167+
postNotificationName:FlutterViewControllerShowHomeIndicator
168+
object:nil];
169+
} else {
170+
[[NSNotificationCenter defaultCenter]
171+
postNotificationName:FlutterViewControllerHideHomeIndicator
172+
object:nil];
173+
}
164174
}
165175

166176
- (void)restoreSystemChromeSystemUIOverlays {

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
static constexpr CGFloat kScrollViewContentSize = 2.0;
2828

2929
NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate";
30-
3130
NSNotificationName const FlutterViewControllerWillDealloc = @"FlutterViewControllerWillDealloc";
31+
NSNotificationName const FlutterViewControllerHideHomeIndicator =
32+
@"FlutterViewControllerHideHomeIndicator";
33+
NSNotificationName const FlutterViewControllerShowHomeIndicator =
34+
@"FlutterViewControllerShowHomeIndicator";
3235

3336
/// Class to coalesce calls for a period of time.
3437
///
@@ -91,6 +94,7 @@ - (void)invalidate {
9194
// just a warning.
9295
@interface FlutterViewController () <FlutterBinaryMessenger, UIScrollViewDelegate>
9396
@property(nonatomic, readwrite, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI;
97+
@property(nonatomic, assign) BOOL isHomeIndicatorHidden;
9498
@end
9599

96100
// The following conditional compilation defines an API 13 concept on earlier API targets so that
@@ -318,6 +322,16 @@ - (void)setupNotificationCenterObservers {
318322
selector:@selector(onUserSettingsChanged:)
319323
name:UIContentSizeCategoryDidChangeNotification
320324
object:nil];
325+
326+
[center addObserver:self
327+
selector:@selector(onHideHomeIndicatorNotification:)
328+
name:FlutterViewControllerHideHomeIndicator
329+
object:nil];
330+
331+
[center addObserver:self
332+
selector:@selector(onShowHomeIndicatorNotification:)
333+
name:FlutterViewControllerShowHomeIndicator
334+
object:nil];
321335
}
322336

323337
- (void)setInitialRoute:(NSString*)route {
@@ -1022,6 +1036,27 @@ - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences {
10221036
}
10231037
}
10241038

1039+
- (void)onHideHomeIndicatorNotification:(NSNotification*)notification {
1040+
self.isHomeIndicatorHidden = YES;
1041+
}
1042+
1043+
- (void)onShowHomeIndicatorNotification:(NSNotification*)notification {
1044+
self.isHomeIndicatorHidden = NO;
1045+
}
1046+
1047+
- (void)setIsHomeIndicatorHidden:(BOOL)hideHomeIndicator {
1048+
if (hideHomeIndicator != _isHomeIndicatorHidden) {
1049+
_isHomeIndicatorHidden = hideHomeIndicator;
1050+
if (@available(iOS 11, *)) {
1051+
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
1052+
}
1053+
}
1054+
}
1055+
1056+
- (BOOL)prefersHomeIndicatorAutoHidden {
1057+
return self.isHomeIndicatorHidden;
1058+
}
1059+
10251060
- (BOOL)shouldAutorotate {
10261061
return YES;
10271062
}

shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m renamed to shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#import <XCTest/XCTest.h>
77
#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
88
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
9+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
910

1011
#include "FlutterBinaryMessenger.h"
1112

@@ -344,67 +345,67 @@ - (void)testPerformOrientationUpdateDoesNotForceOrientationChange {
344345
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
345346
currentOrientation:UIInterfaceOrientationPortrait
346347
didChangeOrientation:NO
347-
resultingOrientation:0];
348+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
348349

349350
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
350351
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
351352
didChangeOrientation:NO
352-
resultingOrientation:0];
353+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
353354

354355
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
355356
currentOrientation:UIInterfaceOrientationLandscapeLeft
356357
didChangeOrientation:NO
357-
resultingOrientation:0];
358+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
358359

359360
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
360361
currentOrientation:UIInterfaceOrientationLandscapeRight
361362
didChangeOrientation:NO
362-
resultingOrientation:0];
363+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
363364

364365
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
365366
currentOrientation:UIInterfaceOrientationPortrait
366367
didChangeOrientation:NO
367-
resultingOrientation:0];
368+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
368369

369370
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
370371
currentOrientation:UIInterfaceOrientationLandscapeLeft
371372
didChangeOrientation:NO
372-
resultingOrientation:0];
373+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
373374

374375
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
375376
currentOrientation:UIInterfaceOrientationLandscapeRight
376377
didChangeOrientation:NO
377-
resultingOrientation:0];
378+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
378379

379380
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
380381
currentOrientation:UIInterfaceOrientationPortrait
381382
didChangeOrientation:NO
382-
resultingOrientation:0];
383+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
383384

384385
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortraitUpsideDown
385386
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
386387
didChangeOrientation:NO
387-
resultingOrientation:0];
388+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
388389

389390
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape
390391
currentOrientation:UIInterfaceOrientationLandscapeLeft
391392
didChangeOrientation:NO
392-
resultingOrientation:0];
393+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
393394

394395
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape
395396
currentOrientation:UIInterfaceOrientationLandscapeRight
396397
didChangeOrientation:NO
397-
resultingOrientation:0];
398+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
398399

399400
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeLeft
400401
currentOrientation:UIInterfaceOrientationLandscapeLeft
401402
didChangeOrientation:NO
402-
resultingOrientation:0];
403+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
403404

404405
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeRight
405406
currentOrientation:UIInterfaceOrientationLandscapeRight
406407
didChangeOrientation:NO
407-
resultingOrientation:0];
408+
resultingOrientation:static_cast<UIInterfaceOrientation>(0)];
408409
}
409410

410411
// Perform an orientation update test that fails when the expected outcome
@@ -465,8 +466,6 @@ - (void)testWillDeallocNotification {
465466
}
466467

467468
- (void)testDoesntLoadViewInInit {
468-
XCTestExpectation* expectation =
469-
[[XCTestExpectation alloc] initWithDescription:@"notification called"];
470469
FlutterDartProject* project = [[FlutterDartProject alloc] init];
471470
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project];
472471
[engine createShell:@"" libraryURI:@""];
@@ -476,4 +475,17 @@ - (void)testDoesntLoadViewInInit {
476475
XCTAssertFalse([realVC isViewLoaded], @"shouldn't have loaded since it hasn't been shown");
477476
}
478477

478+
- (void)testHideOverlay {
479+
FlutterDartProject* project = [[FlutterDartProject alloc] init];
480+
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project];
481+
[engine createShell:@"" libraryURI:@""];
482+
FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine
483+
nibName:nil
484+
bundle:nil];
485+
XCTAssertFalse(realVC.prefersHomeIndicatorAutoHidden, @"");
486+
[[NSNotificationCenter defaultCenter] postNotificationName:FlutterViewControllerHideHomeIndicator
487+
object:nil];
488+
XCTAssertTrue(realVC.prefersHomeIndicatorAutoHidden, @"");
489+
}
490+
479491
@end

shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@
55
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_
66
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_
77

8-
#include "flutter/flow/embedded_views.h"
98
#include "flutter/fml/memory/weak_ptr.h"
10-
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
11-
#include "flutter/shell/common/shell.h"
129
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
13-
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
10+
11+
namespace flutter {
12+
class FlutterPlatformViewsController;
13+
}
1414

1515
FLUTTER_EXPORT
1616
extern NSNotificationName const FlutterViewControllerWillDealloc;
1717

18+
FLUTTER_EXPORT
19+
extern NSNotificationName const FlutterViewControllerHideHomeIndicator;
20+
21+
FLUTTER_EXPORT
22+
extern NSNotificationName const FlutterViewControllerShowHomeIndicator;
23+
1824
@interface FlutterViewController ()
1925

2026
- (fml::WeakPtr<FlutterViewController>)getWeakPtr;

testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
10+
0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
1111
0D1CE5D8233430F400E5D880 /* FlutterChannelsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D1CE5D7233430F400E5D880 /* FlutterChannelsTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
1212
0D4C3FB022DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D4C3FAF22DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
1313
0D52D3BD22C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
@@ -76,7 +76,7 @@
7676
/* End PBXContainerItemProxy section */
7777

7878
/* Begin PBXFileReference section */
79-
0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterViewControllerTest.m; sourceTree = "<group>"; };
79+
0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterViewControllerTest.mm; sourceTree = "<group>"; };
8080
0D1CE5D7233430F400E5D880 /* FlutterChannelsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterChannelsTest.m; sourceTree = "<group>"; };
8181
0D4C3FAF22DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterPluginAppLifeCycleDelegateTest.m; sourceTree = "<group>"; };
8282
0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterBinaryMessengerRelayTest.mm; sourceTree = "<group>"; };
@@ -179,7 +179,7 @@
179179
0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */,
180180
0D6AB6E722BB40CF00EEE540 /* FlutterEngineTest.mm */,
181181
3D8AF6172384C5420033B95F /* FlutterTextInputPluginTest.m */,
182-
0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.m */,
182+
0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.mm */,
183183
0D4C3FAF22DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m */,
184184
);
185185
name = Source;
@@ -391,7 +391,7 @@
391391
files = (
392392
0D6AB6EB22BB40E700EEE540 /* FlutterEngineTest.mm in Sources */,
393393
3D8AF6182384C5420033B95F /* FlutterTextInputPluginTest.m in Sources */,
394-
0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.m in Sources */,
394+
0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.mm in Sources */,
395395
0D1CE5D8233430F400E5D880 /* FlutterChannelsTest.m in Sources */,
396396
0D52D3BD22C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm in Sources */,
397397
0D4C3FB022DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m in Sources */,

0 commit comments

Comments
 (0)