Skip to content

Commit 46fb9a2

Browse files
[iOS] StatusBarBehavior does not occupy entire notch - fix (#2309)
* [iOS] Improve status bar * Use `Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific.Page.GetUseSafeArea`, Remove `CommunityToolkit.Maui.PlatformConfiguration.iOSSpecific.StatusBar`, Remove `OperatingSystem.IsIOSVersionAtLeast(13))` (Toolkit now supports iOS 15+) * Remove iOS 13 check (Toolkit only supports iOS 15+) * Don't modify StatusBar Frame in `PlatformSetColor` * Remove iOS 13 code (Toolkit support iOS 15+ * Refactor * Update azure-pipelines.yml --------- Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>
1 parent 075be1b commit 46fb9a2

File tree

5 files changed

+74
-96
lines changed

5 files changed

+74
-96
lines changed

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ variables:
2929
PathToCommunityToolkitAnalyzersBenchmarkCsproj: 'src/CommunityToolkit.Maui.Analyzers.Benchmarks/CommunityToolkit.Maui.Analyzers.Benchmarks.csproj'
3030
DotNetMauiRollbackFile: 'https://maui.blob.core.windows.net/metadata/rollbacks/8.0.6.json'
3131
CommunityToolkitSampleApp_Xcode_Version: '16.2'
32-
CommunityToolkitLibrary_Xcode_Version: '16.1'
32+
CommunityToolkitLibrary_Xcode_Version: '16.2'
3333

3434
trigger:
3535
branches:

samples/CommunityToolkit.Maui.Sample/Pages/Base/BasePage.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33

44
namespace CommunityToolkit.Maui.Sample.Pages;
55

6-
public abstract class BasePage<TViewModel> : BasePage where TViewModel : BaseViewModel
6+
public abstract class BasePage<TViewModel>(TViewModel viewModel) : BasePage(viewModel)
7+
where TViewModel : BaseViewModel
78
{
8-
protected BasePage(TViewModel viewModel) : base(viewModel)
9-
{
10-
}
11-
129
public new TViewModel BindingContext => (TViewModel)base.BindingContext;
1310
}
1411

samples/CommunityToolkit.Maui.Sample/Pages/Behaviors/StatusBarBehaviorPage.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
77
xmlns:pages="clr-namespace:CommunityToolkit.Maui.Sample.Pages"
88
xmlns:vm="clr-namespace:CommunityToolkit.Maui.Sample.ViewModels.Behaviors"
9+
xmlns:ios="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;assembly=Microsoft.Maui.Controls"
10+
ios:Page.UseSafeArea="True"
911
Title="StatusBarBehavior"
1012
x:DataType="vm:StatusBarBehaviorViewModel"
1113
x:TypeArguments="vm:StatusBarBehaviorViewModel"
@@ -81,7 +83,7 @@
8183

8284
<ScrollView Padding="{StaticResource ContentPadding}">
8385

84-
<VerticalStackLayout Padding="15,0" Spacing="30">
86+
<VerticalStackLayout Padding="15,0" Spacing="30" IgnoreSafeArea="False">
8587

8688
<Label Text="Slide to change StatusBar color" />
8789

src/CommunityToolkit.Maui.Core/Platform/StatusBar/StatusBar.ios.cs

Lines changed: 50 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -11,91 +11,73 @@ static partial class StatusBar
1111
/// <summary>
1212
/// Method to update the status bar size.
1313
/// </summary>
14-
public static void UpdateBarSize()
14+
public static void SetBarSize(bool isUsingSafeArea)
1515
{
16-
if (OperatingSystem.IsIOSVersionAtLeast(13))
16+
var communityToolkitStatusBarTag = new IntPtr(38482);
17+
foreach (var window in UIApplication.SharedApplication.Windows)
1718
{
18-
var statusBarTag = new IntPtr(38482);
19-
foreach (var window in UIApplication.SharedApplication.Windows)
19+
var statusBarFrame = window.WindowScene?.StatusBarManager?.StatusBarFrame;
20+
if (statusBarFrame is null)
2021
{
21-
var statusBar = window.ViewWithTag(statusBarTag);
22-
var statusBarFrame = window.WindowScene?.StatusBarManager?.StatusBarFrame;
23-
if (statusBarFrame is null)
24-
{
25-
continue;
26-
}
27-
28-
statusBar ??= new UIView(statusBarFrame.Value);
29-
statusBar.Tag = statusBarTag;
30-
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
31-
var statusBarSubViews = window.Subviews.Where(x => x.Tag == statusBarTag).ToList();
32-
foreach (var statusBarSubView in statusBarSubViews)
33-
{
34-
statusBarSubView.RemoveFromSuperview();
35-
}
36-
37-
window.AddSubview(statusBar);
38-
39-
TryUpdateStatusBarAppearance(window);
22+
continue;
4023
}
41-
}
42-
else
43-
{
44-
if (UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) is UIView statusBar)
24+
25+
var statusBar = window.ViewWithTag(communityToolkitStatusBarTag) ?? new UIView(statusBarFrame.Value);
26+
statusBar.Tag = communityToolkitStatusBarTag;
27+
statusBar.Frame = GetStatusBarFrame(window, isUsingSafeArea);
28+
29+
var statusBarSubViews = window.Subviews.Where(x => x.Tag == communityToolkitStatusBarTag).ToList();
30+
foreach (var statusBarSubView in statusBarSubViews)
4531
{
46-
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
32+
statusBarSubView.RemoveFromSuperview();
4733
}
4834

49-
TryUpdateStatusBarAppearance();
35+
window.AddSubview(statusBar);
36+
37+
TryUpdateStatusBarAppearance(window);
5038
}
5139
}
5240

5341
static void PlatformSetColor(Color color)
5442
{
5543
var uiColor = color.ToPlatform();
56-
57-
if (OperatingSystem.IsIOSVersionAtLeast(13))
44+
45+
var statusBarTag = new IntPtr(38482);
46+
foreach (var window in UIApplication.SharedApplication.Windows)
5847
{
59-
var statusBarTag = new IntPtr(38482);
60-
foreach (var window in UIApplication.SharedApplication.Windows)
48+
var statusBar = window.ViewWithTag(statusBarTag);
49+
var statusBarFrame = window.WindowScene?.StatusBarManager?.StatusBarFrame;
50+
if (statusBarFrame is null)
6151
{
62-
var statusBar = window.ViewWithTag(statusBarTag);
63-
var statusBarFrame = window.WindowScene?.StatusBarManager?.StatusBarFrame;
64-
if (statusBarFrame is null)
65-
{
66-
continue;
67-
}
68-
69-
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
70-
// window.ViewWithTag(tag) can return null
71-
statusBar ??= new UIView(statusBarFrame.Value);
72-
statusBar.Tag = statusBarTag;
73-
statusBar.BackgroundColor = uiColor;
74-
statusBar.TintColor = uiColor;
75-
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
76-
var statusBarSubViews = window.Subviews.Where(x => x.Tag == statusBarTag).ToList();
77-
foreach (var statusBarSubView in statusBarSubViews)
78-
{
79-
statusBarSubView.RemoveFromSuperview();
80-
}
81-
82-
window.AddSubview(statusBar);
83-
84-
TryUpdateStatusBarAppearance(window);
52+
continue;
8553
}
86-
}
87-
else
88-
{
89-
if (UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) is UIView statusBar
90-
&& statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
54+
55+
statusBar ??= new UIView(statusBarFrame.Value);
56+
statusBar.Tag = statusBarTag;
57+
statusBar.BackgroundColor = uiColor;
58+
statusBar.TintColor = uiColor;
59+
60+
var statusBarSubViews = window.Subviews.Where(x => x.Tag == statusBarTag).ToList();
61+
foreach (var statusBarSubView in statusBarSubViews)
9162
{
92-
statusBar.BackgroundColor = uiColor;
63+
statusBarSubView.RemoveFromSuperview();
9364
}
9465

95-
TryUpdateStatusBarAppearance();
66+
window.AddSubview(statusBar);
67+
68+
TryUpdateStatusBarAppearance(window);
9669
}
9770
}
9871

72+
static CGRect GetStatusBarFrame(in UIWindow window, in bool isUsingSafeArea)
73+
{
74+
var statusBarFrame = UIApplication.SharedApplication.StatusBarFrame;
75+
76+
return isUsingSafeArea
77+
? new CGRect(statusBarFrame.X, statusBarFrame.Y, statusBarFrame.Width, window.SafeAreaInsets.Top)
78+
: statusBarFrame;
79+
}
80+
9981
static void PlatformSetStyle(StatusBarStyle statusBarStyle)
10082
{
10183
var uiStyle = statusBarStyle switch
@@ -113,22 +95,14 @@ static void PlatformSetStyle(StatusBarStyle statusBarStyle)
11395

11496
static bool TryUpdateStatusBarAppearance()
11597
{
116-
if (OperatingSystem.IsIOSVersionAtLeast(13))
117-
{
118-
var didUpdateAllStatusBars = true;
98+
var didUpdateAllStatusBars = true;
11999

120-
foreach (var window in UIApplication.SharedApplication.Windows)
121-
{
122-
didUpdateAllStatusBars &= TryUpdateStatusBarAppearance(window);
123-
}
124-
125-
return didUpdateAllStatusBars;
126-
}
127-
else
100+
foreach (var window in UIApplication.SharedApplication.Windows)
128101
{
129-
var window = UIApplication.SharedApplication.KeyWindow;
130-
return TryUpdateStatusBarAppearance(window);
102+
didUpdateAllStatusBars &= TryUpdateStatusBarAppearance(window);
131103
}
104+
105+
return didUpdateAllStatusBars;
132106
}
133107

134108
static bool TryUpdateStatusBarAppearance(UIWindow? window)

src/CommunityToolkit.Maui/Behaviors/PlatformBehaviors/StatusBar/StatusBarBehavior.shared.cs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,48 +78,53 @@ public StatusBarApplyOn ApplyOn
7878

7979
/// <inheritdoc />
8080
#if IOS
81-
protected override void OnAttachedTo(Page bindable, UIKit.UIView platformView)
81+
protected override void OnAttachedTo(Page page, UIKit.UIView platformView)
8282
#elif ANDROID
83-
protected override void OnAttachedTo(Page bindable, Android.Views.View platformView)
83+
protected override void OnAttachedTo(Page page, Android.Views.View platformView)
8484
#else
85-
protected override void OnAttachedTo(Page bindable, object platformView)
85+
protected override void OnAttachedTo(Page page, object platformView)
8686
#endif
8787
{
88-
base.OnAttachedTo(bindable, platformView);
88+
base.OnAttachedTo(page, platformView);
8989

9090
if (ApplyOn is StatusBarApplyOn.OnBehaviorAttachedTo)
9191
{
92+
#if IOS
93+
StatusBar.SetBarSize(Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific.Page.GetUseSafeArea(page));
94+
#endif
95+
9296
StatusBar.SetColor(StatusBarColor);
9397
StatusBar.SetStyle(StatusBarStyle);
9498
}
9599

96-
bindable.NavigatedTo += OnPageNavigatedTo;
100+
page.NavigatedTo += OnPageNavigatedTo;
97101
#if IOS
98-
bindable.SizeChanged += OnPageSizeChanged;
102+
page.SizeChanged += OnPageSizeChanged;
99103
#endif
100104
}
101105

102106
/// <inheritdoc />
103107
#if IOS
104-
protected override void OnDetachedFrom(Page bindable, UIKit.UIView platformView)
108+
protected override void OnDetachedFrom(Page page, UIKit.UIView platformView)
105109
#elif ANDROID
106-
protected override void OnDetachedFrom(Page bindable, Android.Views.View platformView)
110+
protected override void OnDetachedFrom(Page page, Android.Views.View platformView)
107111
#else
108-
protected override void OnDetachedFrom(Page bindable, object platformView)
112+
protected override void OnDetachedFrom(Page page, object platformView)
109113
#endif
110114
{
111115
#if IOS
112-
bindable.SizeChanged -= OnPageSizeChanged;
116+
page.SizeChanged -= OnPageSizeChanged;
113117
#endif
114-
base.OnDetachedFrom(bindable, platformView);
118+
base.OnDetachedFrom(page, platformView);
115119

116-
bindable.NavigatedTo -= OnPageNavigatedTo;
120+
page.NavigatedTo -= OnPageNavigatedTo;
117121
}
118122

119123
#if IOS
120124
static void OnPageSizeChanged(object? sender, EventArgs e)
121125
{
122-
StatusBar.UpdateBarSize();
126+
ArgumentNullException.ThrowIfNull(sender);
127+
StatusBar.SetBarSize(Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific.Page.GetUseSafeArea((Page)sender));
123128
}
124129
#endif
125130

0 commit comments

Comments
 (0)