Skip to content

Commit b802459

Browse files
CopilotPureWeen
andcommitted
Apply iOS 26 TitleView fix to NavigationPage
Extended the iOS 26+ TitleView fix to NavigationPage in addition to Shell: 1. Added CreateTitleViewContainer helper method to centralize container creation 2. Added Container constructor overload accepting navigation bar frame for iOS 26+ 3. Refactored Container initialization to use InitializeContainer method 4. Updated ToolbarHeight to use actual navigation bar height when available 5. Eliminated hardcoded 44pt height assumption for iOS 26+ This ensures both Shell and NavigationPage TitleView implementations handle iOS 26 layout changes consistently, preventing TitleView from covering page content. Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
1 parent 66e1443 commit b802459

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,13 +1664,34 @@ internal void UpdateTitleArea(Page page)
16641664
if (n is null)
16651665
return;
16661666

1667-
Container titleViewContainer = new Container(titleView, n.NavigationBar);
1667+
Container titleViewContainer = CreateTitleViewContainer(titleView, n.NavigationBar);
16681668

16691669
UpdateTitleImage(titleViewContainer, titleIcon);
16701670
NavigationItem.TitleView = titleViewContainer;
16711671
}
16721672
}
16731673

1674+
/// <summary>
1675+
/// Creates a Container with the appropriate configuration for the current iOS version.
1676+
/// For iOS 26+, uses autoresizing masks and sets frame from navigation bar to prevent layout issues.
1677+
/// </summary>
1678+
Container CreateTitleViewContainer(View titleView, UINavigationBar navigationBar)
1679+
{
1680+
// iOS 26+ requires autoresizing masks and explicit frame sizing to prevent TitleView from covering content
1681+
if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))
1682+
{
1683+
var navigationBarFrame = navigationBar.Frame;
1684+
if (navigationBarFrame != CGRect.Empty)
1685+
{
1686+
return new Container(titleView, navigationBar, navigationBarFrame);
1687+
}
1688+
// Fallback: If navigation bar frame isn't available, use standard constructor
1689+
// The view will still use autoresizing masks (configured in constructor)
1690+
}
1691+
1692+
return new Container(titleView, navigationBar);
1693+
}
1694+
16741695
void UpdateIconColor()
16751696
{
16761697
if (_navigation.TryGetTarget(out NavigationRenderer navigationRenderer))
@@ -2083,13 +2104,35 @@ class Container : UIView
20832104
IPlatformViewHandler _child;
20842105
UIImageView _icon;
20852106
bool _disposed;
2107+
nfloat? _navigationBarHeight;
20862108

20872109
//https://developer.apple.com/documentation/uikit/uiview/2865930-directionallayoutmargins
20882110
const int SystemMargin = 16;
20892111

20902112
public Container(View view, UINavigationBar bar) : base(bar.Bounds)
20912113
{
2092-
// For iOS 26+, we need to use autoresizing masks instead of constraints to ensure proper TitleView display
2114+
InitializeContainer(view, bar, null);
2115+
}
2116+
2117+
/// <summary>
2118+
/// Creates a Container with an explicitly set frame from the navigation bar.
2119+
/// Used on iOS 26+ to ensure proper sizing when using autoresizing masks.
2120+
/// </summary>
2121+
/// <param name="view">The MAUI view to display in the title</param>
2122+
/// <param name="bar">The navigation bar</param>
2123+
/// <param name="navigationBarFrame">The navigation bar frame to use for sizing</param>
2124+
internal Container(View view, UINavigationBar bar, CGRect navigationBarFrame) : base(CGRect.Empty)
2125+
{
2126+
// Set frame to match navigation bar dimensions, starting at origin (0,0)
2127+
Frame = new CGRect(0, 0, navigationBarFrame.Width, navigationBarFrame.Height);
2128+
InitializeContainer(view, bar, navigationBarFrame.Height);
2129+
}
2130+
2131+
void InitializeContainer(View view, UINavigationBar bar, nfloat? navigationBarHeight)
2132+
{
2133+
// iOS 26+ and MacCatalyst 26+ require autoresizing masks instead of constraints
2134+
// to prevent TitleView from expanding beyond navigation bar bounds and covering content.
2135+
// This is a workaround for layout behavior changes in iOS 26.
20932136
if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))
20942137
{
20952138
TranslatesAutoresizingMaskIntoConstraints = true;
@@ -2106,6 +2149,8 @@ public Container(View view, UINavigationBar bar) : base(bar.Bounds)
21062149
}
21072150

21082151
_bar = bar as MauiControlsNavigationBar;
2152+
_navigationBarHeight = navigationBarHeight;
2153+
21092154
if (view != null)
21102155
{
21112156
_view = view;
@@ -2170,9 +2215,16 @@ nfloat ToolbarHeight
21702215
{
21712216
get
21722217
{
2218+
// For iOS 26+, use the actual navigation bar height if available
2219+
if (_navigationBarHeight.HasValue)
2220+
return _navigationBarHeight.Value;
2221+
21732222
if (Superview?.Bounds.Height > 0)
21742223
return Superview.Bounds.Height;
21752224

2225+
// Fallback to device-specific defaults
2226+
// Note: iOS 26+ uses taller navigation bars, but this fallback
2227+
// should rarely be hit as we prefer using the actual navigation bar frame
21762228
return (DeviceInfo.Idiom == DeviceIdiom.Phone && DeviceDisplay.MainDisplayInfo.Orientation.IsLandscape()) ? 32 : 44;
21772229
}
21782230
}

0 commit comments

Comments
 (0)