Skip to content

[iOS] Fix Stepper layout overlap in landscape on iOS 26#34325

Merged
kubaflo merged 5 commits intodotnet:inflight/currentfrom
Vignesh-SF3580:fix-34273
Mar 10, 2026
Merged

[iOS] Fix Stepper layout overlap in landscape on iOS 26#34325
kubaflo merged 5 commits intodotnet:inflight/currentfrom
Vignesh-SF3580:fix-34273

Conversation

@Vignesh-SF3580
Copy link
Copy Markdown
Contributor

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!

Issue Details

On iOS 26 (Liquid Glass), a Stepper and Label placed in a HorizontalStackLayout visually overlap after rotating the simulator to landscape orientation. The overlap does not occur in portrait, nor on iOS versions prior to 26.

Root Cause

iOS 26 introduced a Liquid Glass design system where UIStepper renders a glass pill that visually extends beyond the control’s logical frame on the trailing (right) edge, with Layer.MasksToBounds = false. In landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize, AlignmentRectInsets) continue to report the logical size of 94×32pt and are unaware of the glass overflow. MAUI’s layout engine relies on these values and positions the adjacent Label at X=94, which falls inside the visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no compensation is required.

Description of Change

GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on iOS 26 or later in landscape orientation, a 20pt width compensation is added to the reported desired size. This causes MAUI’s HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt, positioning the adjacent Label at X=114—safely outside the glass pill’s visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width > Bounds.Height, which is reliable because GetDesiredSize is invoked after the layout transition completes.
A minor namespace update was also made: using System.Drawing → using Microsoft.Maui.Graphics to resolve the Size return type without ambiguity. RectangleF.Empty is explicitly qualified as System.Drawing.RectangleF.Empty.

Issues Fixed

Fixes #34273

Key Technical Details

Detail Value
Affected platform iOS only (StepperHandler.iOS.cs)
iOS version guard OperatingSystem.IsIOSVersionAtLeast(26)
Orientation detection UIScreen.MainScreen.Bounds.Width > Bounds.Height
Compensation amount 20pt (glass pill overflow measured empirically)
MAUI API hook GetDesiredSize override (called by HorizontalStackLayout measurement)
Portrait behaviour Unchanged — no 20pt is added in portrait
Public API addition override StepperHandler.GetDesiredSize(double, double) -> Size

Files Changed

File Change
src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs Add GetDesiredSize override with iOS 26 landscape compensation (+24 lines); namespace fix System.DrawingMicrosoft.Maui.Graphics
src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Add public API entry for GetDesiredSize override

Screenshots

Before Issue Fix After Issue Fix
34273BeforeFix.mov
34273AfterFix.mov

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 4, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34325

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34325"

@dotnet-policy-service dotnet-policy-service bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Mar 4, 2026
@Vignesh-SF3580 Vignesh-SF3580 added the community ✨ Community Contribution label Mar 4, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review March 6, 2026 14:13
Copilot AI review requested due to automatic review settings March 6, 2026 14:13
@sheiksyedm sheiksyedm added this to the .NET 10 SR7 milestone Mar 6, 2026
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

Fixes an iOS 26 landscape-specific visual overlap where UIStepper’s Liquid Glass rendering extends beyond its reported measure, causing adjacent controls (e.g., Label in a HorizontalStackLayout) to overlap.

Changes:

  • Override StepperHandler.GetDesiredSize on iOS to add a landscape-only width compensation on iOS 26+.
  • Add PublicAPI entries for the new StepperHandler.GetDesiredSize override (iOS + MacCatalyst TFMs).
  • Add a new HostApp repro page + UITests and update Android snapshot baseline.

Reviewed changes

Copilot reviewed 5 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs Adds iOS 26+ landscape width compensation in GetDesiredSize to prevent visual overlap.
src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Records the new iOS public API surface for the override.
src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Records the new MacCatalyst public API surface for the override (file compiles for this TFM too).
src/Controls/tests/TestCases.HostApp/Issues/Issue34273.cs Adds a repro page with Stepper/Label + Editor binding scenario.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34273.cs Adds screenshot-based UITests that rotate orientation and verify no overlap.
src/Controls/tests/TestCases.Android.Tests/snapshots/android/EditorNoOverlapAfterRotateToLandscape.png Adds/updates Android snapshot baseline for the new landscape rotation test.

Comment on lines +1 to +2
#nullable enable
override Microsoft.Maui.Handlers.StepperHandler.GetDesiredSize(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

PR description says the PublicAPI update is in net-ios only, but this PR also changes net-maccatalyst/PublicAPI.Unshipped.txt. Please update the PR description/table to reflect both files (or explain why MacCatalyst also needs the API entry).

Copilot uses AI. Check for mistakes.
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Mar 7, 2026

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review SessionAdded snapshots. · 04d4cf7

Issue: #34273 - [.NET10] D10 - Customize cursor position - Rotating simulator makes the button and label overlap
PR: #34325 - [iOS] Fix Stepper layout overlap in landscape on iOS 26
Author: Vignesh-SF3580 (Syncfusion partner contributor)
Platforms Affected: iOS only (iOS 26+ specific)
Labels: platform/ios, area-controls-stepper, version/iOS-26, community ✨, partner/syncfusion

Issue Summary

On iOS 26 (Liquid Glass design system), a Stepper and Label placed inside a HorizontalStackLayout visually overlap after rotating to landscape orientation. The bug is iOS 26+ specific:

  • UIStepper renders a Liquid Glass pill that visually extends beyond its logical frame (Layer.MasksToBounds = false)
  • All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize, AlignmentRectInsets) still report the logical size (94×32 pt) and are unaware of the glass overflow
  • In landscape, the overflow is ~18–20 pt, causing adjacent controls to appear inside the glass pill
  • Portrait orientation has negligible overflow — no bug there

The issue was confirmed as a regression starting from 10.0.0-rc2, not reproducible in 9.0.120.

Files Changed

File Type Change
src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs Fix Override GetDesiredSize with iOS 26 landscape compensation (+38 lines); namespace System.DrawingMicrosoft.Maui.Graphics
src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Fix Add public API entry for GetDesiredSize override
src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Fix Add public API entry (StepperHandler.iOS.cs compiles for both TFMs)
src/Controls/tests/TestCases.HostApp/Issues/Issue34273.cs Test New HostApp repro page with Stepper/Label + Editor binding
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34273.cs Test Two screenshot-based UITests: rotate to landscape, and rotate back to portrait
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/EditorNoOverlapAfterRotateToLandscape.png Test iOS 26 snapshot baseline
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/EditorNoOverlapAfterRotateToPortrait.png Test iOS 26 snapshot baseline
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EditorNoOverlapAfterRotateToLandscape.png Test iOS snapshot baseline
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EditorNoOverlapAfterRotateToPortrait.png Test iOS snapshot baseline
src/Controls/tests/TestCases.Android.Tests/snapshots/android/EditorNoOverlapAfterRotateToLandscape.png Test Android snapshot baseline
src/Controls/tests/TestCases.Android.Tests/snapshots/android/EditorNoOverlapAfterRotateToPortrait.png Test Android snapshot baseline

PR Discussion / Reviewer Feedback

Copilot auto-review identified:

  1. Spelling issues in HostApp test page (Issue34273.cs): "strong" → "string", "pree" → "press", "The tests fails" → "The test fails", unclosed (NOTE: parenthesis
  2. Comment inaccuracy: PR says "Mac displays are always landscape" — but MacCatalyst apps can run in resizable windows
  3. net-maccatalyst/PublicAPI.Unshipped.txt was changed but not mentioned in the PR description
File:Line Reviewer Says Status
Issue34273.cs:52 "pree" should be "press" ⚠️ Minor spelling issue
Issue34273.cs:52 "strong" should be "string", unclosed (NOTE: ⚠️ Minor typos
Issue34273.cs:49 "The tests fails" should be "The test fails" ⚠️ Minor grammar
StepperHandler.iOS.cs:39 "Mac displays are always landscape" comment is inaccurate ⚠️ Inaccurate comment
PublicAPI net-maccatalyst:2 MacCatalyst API entry not mentioned in PR description ⚠️ Documentation gap

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34325 Override GetDesiredSize in StepperHandler.iOS.cs; add 20pt width compensation when OperatingSystem.IsIOS() && IsIOSVersionAtLeast(26) and orientation is landscape (detected via UIScreen.MainScreen.Bounds.Width > Bounds.Height) ⏳ PENDING (Gate) StepperHandler.iOS.cs (+38), 2 PublicAPI files Original PR

🚦 Gate — Test Verification
📝 Review SessionAdded snapshots. · 04d4cf7

Result: ✅ PASSED
Platform: ios (iPhone Xs Simulator, iOS 18.6)
Mode: Full Verification
Test Filter: Issue34273

  • Tests FAIL without fix ✅
  • Tests PASS with fix ✅

Test Results

Test Result
EditorNoOverlapAfterRotateToLandscape ✅ PASS
EditorNoOverlapAfterRotateToPortrait ✅ PASS

Total: 2 passed, 0 failed, 0 skipped


🔧 Fix — Analysis & Comparison
📝 Review SessionAdded snapshots. · 04d4cf7

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Private MauiStepper : UIStepper subclass overriding SizeThatFits, add 20pt landscape iOS 26+ ✅ PASS 1 file (StepperHandler.iOS.cs) No public API change; cleaner API surface
2 try-fix Controls-level Stepper.iOS.cs new partial file overriding MeasureOverride, add 20pt ✅ PASS 3 files (new partial + 2 PublicAPI) Works highest in stack; adds public API
3 try-fix ClipsToBounds = true + Layer.MasksToBounds = true in ConnectHandler ✅ PASS* 2 files* *Clips the Liquid Glass visual — degrades iOS 26 UX; *also required VisualRegressionTester.cs changes
4 try-fix AlignmentRectInsets property override in private UIStepper subclass ❌ FAIL Build error: NFloat type mismatch
5 try-fix AlignmentRectInsets override + UIDevice.OrientationDidChangeNotification observer ✅ PASS 1 file (StepperHandler.iOS.cs) Orientation-reactive; no public API change
6 try-fix StepperWrapperView : WrapperView container view wrapping UIStepper ✅ PASS 3 files Most complex; adds 2 new public APIs; required VisualRegressionTester.cs to be restored
PR PR #34325 Override GetDesiredSize on handler; add 20pt when iOS 26+ landscape ✅ PASS (Gate) 3 files (StepperHandler.iOS.cs + 2 PublicAPI) Original PR; MAUI-idiomatic handler API

*Attempt 3 is disqualified from selection: clips the iOS 26 Liquid Glass pill rendering entirely, removing the system design aesthetic.

Cross-Pollination Table

Round Model Response
2 claude-sonnet-4.6 NEW IDEA: container UIView
2 claude-opus-4.6 NO NEW IDEAS
2 gpt-5.2 NEW IDEA: container UIView
2 gpt-5.3-codex NO NEW IDEAS
2 gemini-3-pro-preview NEW IDEA: container UIView → led to Attempt 6
3 claude-sonnet-4.6 NEW IDEA: read AlignmentRectInsets dynamically → ruled out (returns 0,0,0,0)
3 claude-opus-4.6 NO NEW IDEAS
3 gpt-5.2 NEW IDEA: replace UIStepper with UIButtons → ruled out (too complex)
3 gpt-5.3-codex NO NEW IDEAS
3 gemini-3-pro-preview NEW IDEA: SetBackgroundImage → ruled out (removes Liquid Glass styling)
4 claude-sonnet-4.6 NO NEW IDEAS
4 claude-opus-4.6 NO NEW IDEAS
4 gpt-5.2 NEW IDEA: CALayer mask → ruled out (same category as A3 clipping)
4 gpt-5.3-codex NO NEW IDEAS
4 gemini-3-pro-preview NEW IDEA: Dynamic Margin via mapper → ruled out (mutates MAUI Margin, visible side-effect)
5 claude-sonnet-4.6 NEW IDEA: override didAddSubview to clamp Liquid Glass sublayer → ruled out (private UIKit internals)
5 gpt-5.2 NEW IDEA: shadowPath on glass sublayer → ruled out (private UIKit internals)
5 gemini-3-pro-preview NEW IDEA: LayoutSubviews clamp internal subviews → ruled out (private UIKit internals)

Exhausted: Yes — all remaining Round 5 ideas rely on undocumented UIKit private subview/sublayer internals and are not appropriate for production use.

Selected Fix

Selected Fix: PR's fixGetDesiredSize override in StepperHandler.iOS.cs

Reason: The PR's handler-level GetDesiredSize override is the MAUI-idiomatic approach. It hooks into the official MAUI measurement pipeline at the correct abstraction level. While Attempt 1 (SizeThatFits) avoids a public API addition, GetDesiredSize is the documented handler contract for custom size reporting and is more robust (doesn't depend on internal MAUI implementation details about which UIKit method gets called for measurement). The PR's fix is well-commented and correctly guarded with OperatingSystem.IsIOS() && OperatingSystem.IsIOSVersionAtLeast(26).

Concerns to flag (minor):

  1. Inaccurate comment: "Mac displays are always landscape" — MacCatalyst supports resizable windows
  2. Spelling errors in HostApp test page (already flagged by Copilot auto-reviewer)
  3. MacCatalyst PublicAPI change not mentioned in PR description table

📋 Report — Final Recommendation
📝 Review SessionAdded snapshots. · 04d4cf7

✅ Final Recommendation: APPROVE

Summary

PR #34325 fixes a confirmed iOS 26 regression where UIStepper's Liquid Glass pill rendering extends ~20pt beyond the control's logical frame in landscape orientation, causing visual overlap with adjacent controls in HorizontalStackLayout. The fix is well-reasoned, correctly placed in the MAUI handler measurement pipeline, and is properly guarded for iOS 26+ only. Tests pass both with and without the fix (Gate: ✅ PASSED on iOS).


Root Cause

iOS 26 introduced the Liquid Glass design system. UIStepper renders a glass pill that visually overflows its logical frame by ~20pt on the trailing edge in landscape, with Layer.MasksToBounds = false. All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize, AlignmentRectInsets) still report the pre-glass logical size (94×32 pt) and are unaware of the visual overflow. MAUI's HorizontalStackLayout uses these reported sizes for layout, placing the adjacent Label at X=94 — inside the visible glass pill.


Fix Quality

Approach: Override GetDesiredSize in StepperHandler.iOS.cs to add a 20pt width compensation when running on iOS 26+ in landscape orientation.

Strengths:

  • ✅ Correct API hook — GetDesiredSize is the MAUI-idiomatic handler-level measurement override
  • ✅ Tight guards: OperatingSystem.IsIOS() && OperatingSystem.IsIOSVersionAtLeast(26) correctly excludes MacCatalyst
  • ✅ Landscape-only: portrait behavior unchanged
  • ✅ Well-commented constant iOSLiquidGlassStepperOverflow = 20 with explanation and issue link
  • ✅ Tests cover both rotate-to-landscape and rotate-back-to-portrait scenarios
  • ✅ Snapshot baselines for ios, ios-26, and android environments

The agent explored 6 independent alternatives. The hardcoded 20pt offset appeared in every viable alternative — Apple does not expose the glass pill overflow extent through any public UIKit API. The PR's handler-level approach is the most idiomatic choice in MAUI's architecture.


Issues Found (Minor — Does Not Block Approval)

🟡 Inaccurate comment in StepperHandler.iOS.cs (~line 39):

"Mac displays are always landscape and UIStepper on Mac has no glass pill overflow."

MacCatalyst apps can run in resizable windows at any aspect ratio, so "always landscape" is incorrect. The fix code itself is correct (OperatingSystem.IsIOS() properly excludes MacCatalyst), but the comment is misleading for future maintainers.

Suggested replacement (already proposed by Copilot reviewer):

// This workaround targets iOS 26+ only; UIStepper on MacCatalyst has not shown the
// same glass pill overflow behavior in testing.

🟡 MacCatalyst PublicAPI file not mentioned in PR description:
The PR's Files Changed table omits src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt, which is also changed (because StepperHandler.iOS.cs compiles for both iOS and MacCatalyst TFMs). Minor documentation gap.

🟡 Spelling/grammar errors in HostApp test page (Issue34273.cs):
Already flagged by Copilot auto-reviewer:

  • Line 48: "strong" → "string" and unclosed (NOTE: parenthesis
  • Line 49: "The tests fails" → "The test fails"
  • Line 52: "pree" → "press"

🟡 Test category mismatch:
Tests use [Category(UITestCategories.Editor)]. The scenario involves a Stepper, but since the HostApp page is built around an Editor control for cursor position testing, this category isn't entirely wrong — just slightly indirect.


PR Finalization (Title & Description)

Title: ✅ Good as-is

[iOS] Fix Stepper layout overlap in landscape on iOS 26

Description: ✅ Excellent quality — well-structured with Root Cause, Description of Change, Key Technical Details table, Files Changed table, before/after screenshots, and NOTE block. Keep as-is with the addition of:

  1. Add net-maccatalyst/PublicAPI.Unshipped.txt to the Files Changed table

Suggested addition to "What NOT to Do" (for future agents):

### What NOT to Do (for future agents)
- ❌ **Don't set `ClipsToBounds = true`** — clips the Liquid Glass pill entirely, removing the iOS 26 design aesthetic
- ❌ **Don't try to read `AlignmentRectInsets` dynamically** — native UIStepper returns (0,0,0,0); the glass overflow is NOT reflected in this property  
- ❌ **Don't try to walk private sublayers** — Liquid Glass internals are undocumented UIKit implementation details that could change any release

Cross-Model Validation

6 independent try-fix approaches were explored across 5 AI models. Key finding: the 20pt hardcoded compensation is unavoidable — Apple provides no public API to query the glass pill visual extent. All viable approaches (SizeThatFits override, MeasureOverride partial class, AlignmentRectInsets override, WrapperView container) still require the same empirical 20pt value. The PR's GetDesiredSize override at the handler level is the most MAUI-idiomatic choice.


📋 Expand PR Finalization Review
Title: ✅ Good

Current: [iOS] Fix Stepper layout overlap in landscape on iOS 26

Description: ✅ Good

Description needs updates. See details below.

✨ Suggested PR Description

[!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!

Issue Details

On iOS 26 (Liquid Glass), a Stepper and Label placed in a HorizontalStackLayout visually overlap after rotating the simulator to landscape orientation. The overlap does not occur in portrait, nor on iOS versions prior to 26.

Root Cause

iOS 26 introduced a Liquid Glass design system where UIStepper renders a glass pill that visually extends beyond the control's logical frame on the trailing (right) edge, with Layer.MasksToBounds = false. In landscape orientation, this overflow is approximately 18–20pt.

All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize, AlignmentRectInsets) continue to report the logical size of 94×32pt and are unaware of the glass overflow. MAUI's layout engine relies on these values and positions the adjacent Label at X=94, which falls inside the visible glass pill area. In portrait orientation, the glass overflow is negligible, so no compensation is required.

Description of Change

GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on iOS 26 or later in landscape orientation, a 20pt width compensation is added to the reported desired size. This causes MAUI's HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt, positioning the adjacent Label at X=114—safely outside the glass pill's visual extent.

Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width > Bounds.Height, which is reliable because GetDesiredSize is invoked after the layout transition completes.

A minor namespace update was also made: using System.Drawingusing Microsoft.Maui.Graphics to resolve the Size return type without ambiguity. RectangleF.Empty is explicitly qualified as System.Drawing.RectangleF.Empty.

Issues Fixed

Fixes #34273

Key Technical Details

Detail Value
Affected platform iOS only (runtime guard: OperatingSystem.IsIOS())
MacCatalyst Public API override added (same file, both TFMs), but guard excludes it at runtime — no glass pill overflow on Mac
iOS version guard OperatingSystem.IsIOSVersionAtLeast(26)
Orientation detection UIScreen.MainScreen.Bounds.Width > Bounds.Height
Compensation amount 20pt (glass pill overflow measured empirically on iOS 26.1)
MAUI API hook GetDesiredSize override (called by HorizontalStackLayout measurement)
Portrait behaviour Unchanged — no 20pt is added in portrait
Public API addition override StepperHandler.GetDesiredSize(double, double) -> Size (iOS + MacCatalyst)

Files Changed

File Change
src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs Add GetDesiredSize override with iOS 26 landscape compensation (+38/-2 lines); namespace fix System.DrawingMicrosoft.Maui.Graphics
src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Add public API entry for GetDesiredSize override
src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Add public API entry for GetDesiredSize override (file compiles for both TFMs)
src/Controls/tests/TestCases.HostApp/Issues/Issue34273.cs Add HostApp UI test page with Stepper+Label+Editor repro scenario (+64 lines)
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34273.cs Add NUnit UI tests for landscape and portrait rotation scenarios (+46 lines)
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ Baseline screenshots for iOS (portrait and landscape)
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/ Baseline screenshots for iOS 26 environment (portrait and landscape)
src/Controls/tests/TestCases.Android.Tests/snapshots/android/ Baseline screenshots for Android (portrait and landscape)

Screenshots

Before Issue Fix After Issue Fix
(see issue #34273) (see PR snapshots)
Code Review: ⚠️ Issues Found

Code Review — PR #34325

✅ Looks Good

  • Core logic is sound. The GetDesiredSize override correctly calls base.GetDesiredSize first, then applies the empirical 20pt compensation only under the precise conditions: iOS only (not MacCatalyst), iOS 26+, and landscape orientation. The guards are correct and layered well.
  • MacCatalyst correctly excluded. OperatingSystem.IsIOS() returns false on MacCatalyst. The comment in the code explains this clearly. This is the right pattern for a file that compiles for both TFMs.
  • Comment quality is excellent. The inline comments in GetDesiredSize explain the root cause, the empirical nature of the constant, and future maintenance guidance with a link to the issue. This is exemplary.
  • PublicAPI.Unshipped.txt updated correctly for both net-ios and net-maccatalyst.
  • Namespace change is correct. Switching from System.Drawing to Microsoft.Maui.Graphics for Size and qualifying RectangleF.Empty as System.Drawing.RectangleF.Empty avoids ambiguity cleanly.
  • UI tests added with VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2)) — correct pattern for orientation-change tests where layout settles asynchronously.

🟡 Suggestions

1. Test method names and category reference "Editor" instead of "Stepper"

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

Problem: The test methods are named EditorNoOverlapAfterRotateToLandscape and EditorNoOverlapAfterRotateToPortrait, and use [Category(UITestCategories.Editor)]. The issue is about a Stepper overlapping a Label due to the Liquid Glass glass pill — the Editor is a supporting element in the repro page (used for cursor position binding), not the subject of the overlap.

This naming is misleading: the snapshot files are also named EditorNoOverlapAfterRotateToLandscape.png and EditorNoOverlapAfterRotateToPortrait.png.

Recommendation:

// ✅ Better names:
[Category(UITestCategories.Stepper)]
public void StepperNoOverlapAfterRotateToLandscape() { ... }

public void StepperNoOverlapAfterRotateToPortrait() { ... }

Snapshot files should be renamed accordingly (or re-recorded with the corrected test names). Using UITestCategories.Stepper ensures this test is picked up in Stepper CI runs rather than Editor runs.


2. UIScreen.MainScreen is deprecated on iOS 16+

File: src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs

Problem:

var screen = UIKit.UIScreen.MainScreen;
bool isLandscape = screen.Bounds.Width > screen.Bounds.Height;

UIScreen.MainScreen was deprecated in iOS 16. Apple recommends obtaining the screen from the window scene (view.window?.windowScene?.screen).

Recommendation: Access screen bounds through the platform view's window scene:

var screen = PlatformView?.Window?.WindowScene?.Screen ?? UIKit.UIScreen.MainScreen;
bool isLandscape = screen.Bounds.Width > screen.Bounds.Height;

This uses the non-deprecated path when a window scene is available (the common case once the view is in the hierarchy), and falls back to MainScreen for robustness. Note: GetDesiredSize is called during layout, so PlatformView.Window may be null in early measurement passes — the fallback is therefore important.

Alternatively, if PlatformView.Window is null (meaning the view isn't yet attached to a scene), landscape detection could simply return false (i.e., assume portrait/no-compensation), since the first real layout pass after the view is visible will re-measure correctly.


3. HostApp label instructions describe cursor positioning, not the overlap repro

File: src/Controls/tests/TestCases.HostApp/Issues/Issue34273.cs

Problem: The six Label texts in the HostApp page describe how to use the Stepper to control cursor position in an Editor — a different (older?) issue scenario. They don't guide a tester toward the actual bug: "rotate to landscape and observe the Stepper and Label visually overlap."

This won't affect automated screenshot tests, but makes the page confusing for anyone doing manual validation.

Recommendation: Replace the instructional Labels with ones relevant to the overlap issue, or at minimum add a header Label like:

new Label { Text = "Rotate to landscape — Stepper and Label should NOT overlap (iOS 26 fix)." }

4. Android snapshot baselines are included but the fix is iOS-only

Files: src/Controls/tests/TestCases.Android.Tests/snapshots/android/EditorNoOverlapAfterRotateToLandscape.png, ...Portrait.png

Observation: The test is guarded with #if IOS || ANDROID, so it runs on Android too. Android doesn't have this bug (no glass pill), so the Android snapshots serve as a baseline for the unaffected platform. This is acceptable, but worth noting: Android orientation change may have slightly different timing characteristics. If the Android screenshots become a source of flakiness in CI, restricting the test to #if IOS would be reasonable (with a note that Android is unaffected by design).


🔴 Critical Issues

None.


@kubaflo kubaflo added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 7, 2026
- Fix spelling: 'strong' → 'string', 'pree' → 'press', 'tests fails' → 'test fails'
- Close unclosed parenthesis in instructional text
- Update MacCatalyst comment to accurately describe behavior (Mac apps use resizable windows, not always landscape)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo kubaflo changed the base branch from main to inflight/current March 10, 2026 00:27
@kubaflo kubaflo merged commit 536f66a into dotnet:inflight/current Mar 10, 2026
3 of 12 checks passed
PureWeen pushed a commit that referenced this pull request Mar 11, 2026
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
On iOS 26 (Liquid Glass), a Stepper and Label placed in a
HorizontalStackLayout visually overlap after rotating the simulator to
landscape orientation. The overlap does not occur in portrait, nor on
iOS versions prior to 26.

### Root Cause
iOS 26 introduced a Liquid Glass design system where UIStepper renders a
glass pill that visually extends beyond the control’s logical frame on
the trailing (right) edge, with Layer.MasksToBounds = false. In
landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize,
AlignmentRectInsets) continue to report the logical size of 94×32pt and
are unaware of the glass overflow. MAUI’s layout engine relies on these
values and positions the adjacent Label at X=94, which falls inside the
visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no
compensation is required.

### Description of Change
GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on
iOS 26 or later in landscape orientation, a 20pt width compensation is
added to the reported desired size. This causes MAUI’s
HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt,
positioning the adjacent Label at X=114—safely outside the glass pill’s
visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width >
Bounds.Height, which is reliable because GetDesiredSize is invoked after
the layout transition completes.
A minor namespace update was also made: using System.Drawing → using
Microsoft.Maui.Graphics to resolve the Size return type without
ambiguity. RectangleF.Empty is explicitly qualified as
System.Drawing.RectangleF.Empty.

### Issues Fixed
Fixes #34273

### Key Technical Details

| Detail | Value |
|--------|-------|
| Affected platform | iOS only (`StepperHandler.iOS.cs`) |
| iOS version guard | `OperatingSystem.IsIOSVersionAtLeast(26)` |
| Orientation detection | `UIScreen.MainScreen.Bounds.Width >
Bounds.Height` |
| Compensation amount | 20pt (glass pill overflow measured empirically)
|
| MAUI API hook | `GetDesiredSize` override (called by
`HorizontalStackLayout` measurement) |
| Portrait behaviour | Unchanged — no 20pt is added in portrait |
| Public API addition | `override StepperHandler.GetDesiredSize(double,
double) -> Size` |

### Files Changed

| File | Change |
|------|--------|
| `src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs` | Add
`GetDesiredSize` override with iOS 26 landscape compensation (+24
lines); namespace fix `System.Drawing` → `Microsoft.Maui.Graphics` |
| `src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt` | Add public
API entry for `GetDesiredSize` override |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/77fee2cd-df2f-4057-a9f3-0af75ce5e0eb">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/86ceaacf-7b02-47cb-997a-1b8c71353064">)
|

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions bot pushed a commit that referenced this pull request Mar 11, 2026
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
On iOS 26 (Liquid Glass), a Stepper and Label placed in a
HorizontalStackLayout visually overlap after rotating the simulator to
landscape orientation. The overlap does not occur in portrait, nor on
iOS versions prior to 26.

### Root Cause
iOS 26 introduced a Liquid Glass design system where UIStepper renders a
glass pill that visually extends beyond the control’s logical frame on
the trailing (right) edge, with Layer.MasksToBounds = false. In
landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize,
AlignmentRectInsets) continue to report the logical size of 94×32pt and
are unaware of the glass overflow. MAUI’s layout engine relies on these
values and positions the adjacent Label at X=94, which falls inside the
visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no
compensation is required.

### Description of Change
GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on
iOS 26 or later in landscape orientation, a 20pt width compensation is
added to the reported desired size. This causes MAUI’s
HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt,
positioning the adjacent Label at X=114—safely outside the glass pill’s
visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width >
Bounds.Height, which is reliable because GetDesiredSize is invoked after
the layout transition completes.
A minor namespace update was also made: using System.Drawing → using
Microsoft.Maui.Graphics to resolve the Size return type without
ambiguity. RectangleF.Empty is explicitly qualified as
System.Drawing.RectangleF.Empty.

### Issues Fixed
Fixes #34273

### Key Technical Details

| Detail | Value |
|--------|-------|
| Affected platform | iOS only (`StepperHandler.iOS.cs`) |
| iOS version guard | `OperatingSystem.IsIOSVersionAtLeast(26)` |
| Orientation detection | `UIScreen.MainScreen.Bounds.Width >
Bounds.Height` |
| Compensation amount | 20pt (glass pill overflow measured empirically)
|
| MAUI API hook | `GetDesiredSize` override (called by
`HorizontalStackLayout` measurement) |
| Portrait behaviour | Unchanged — no 20pt is added in portrait |
| Public API addition | `override StepperHandler.GetDesiredSize(double,
double) -> Size` |

### Files Changed

| File | Change |
|------|--------|
| `src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs` | Add
`GetDesiredSize` override with iOS 26 landscape compensation (+24
lines); namespace fix `System.Drawing` → `Microsoft.Maui.Graphics` |
| `src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt` | Add public
API entry for `GetDesiredSize` override |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/77fee2cd-df2f-4057-a9f3-0af75ce5e0eb">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/86ceaacf-7b02-47cb-997a-1b8c71353064">)
|

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen mentioned this pull request Mar 17, 2026
PureWeen pushed a commit that referenced this pull request Mar 19, 2026
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
On iOS 26 (Liquid Glass), a Stepper and Label placed in a
HorizontalStackLayout visually overlap after rotating the simulator to
landscape orientation. The overlap does not occur in portrait, nor on
iOS versions prior to 26.

### Root Cause
iOS 26 introduced a Liquid Glass design system where UIStepper renders a
glass pill that visually extends beyond the control’s logical frame on
the trailing (right) edge, with Layer.MasksToBounds = false. In
landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize,
AlignmentRectInsets) continue to report the logical size of 94×32pt and
are unaware of the glass overflow. MAUI’s layout engine relies on these
values and positions the adjacent Label at X=94, which falls inside the
visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no
compensation is required.

### Description of Change
GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on
iOS 26 or later in landscape orientation, a 20pt width compensation is
added to the reported desired size. This causes MAUI’s
HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt,
positioning the adjacent Label at X=114—safely outside the glass pill’s
visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width >
Bounds.Height, which is reliable because GetDesiredSize is invoked after
the layout transition completes.
A minor namespace update was also made: using System.Drawing → using
Microsoft.Maui.Graphics to resolve the Size return type without
ambiguity. RectangleF.Empty is explicitly qualified as
System.Drawing.RectangleF.Empty.

### Issues Fixed
Fixes #34273

### Key Technical Details

| Detail | Value |
|--------|-------|
| Affected platform | iOS only (`StepperHandler.iOS.cs`) |
| iOS version guard | `OperatingSystem.IsIOSVersionAtLeast(26)` |
| Orientation detection | `UIScreen.MainScreen.Bounds.Width >
Bounds.Height` |
| Compensation amount | 20pt (glass pill overflow measured empirically)
|
| MAUI API hook | `GetDesiredSize` override (called by
`HorizontalStackLayout` measurement) |
| Portrait behaviour | Unchanged — no 20pt is added in portrait |
| Public API addition | `override StepperHandler.GetDesiredSize(double,
double) -> Size` |

### Files Changed

| File | Change |
|------|--------|
| `src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs` | Add
`GetDesiredSize` override with iOS 26 landscape compensation (+24
lines); namespace fix `System.Drawing` → `Microsoft.Maui.Graphics` |
| `src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt` | Add public
API entry for `GetDesiredSize` override |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/77fee2cd-df2f-4057-a9f3-0af75ce5e0eb">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/86ceaacf-7b02-47cb-997a-1b8c71353064">)
|

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions bot pushed a commit that referenced this pull request Mar 20, 2026
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
On iOS 26 (Liquid Glass), a Stepper and Label placed in a
HorizontalStackLayout visually overlap after rotating the simulator to
landscape orientation. The overlap does not occur in portrait, nor on
iOS versions prior to 26.

### Root Cause
iOS 26 introduced a Liquid Glass design system where UIStepper renders a
glass pill that visually extends beyond the control’s logical frame on
the trailing (right) edge, with Layer.MasksToBounds = false. In
landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize,
AlignmentRectInsets) continue to report the logical size of 94×32pt and
are unaware of the glass overflow. MAUI’s layout engine relies on these
values and positions the adjacent Label at X=94, which falls inside the
visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no
compensation is required.

### Description of Change
GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on
iOS 26 or later in landscape orientation, a 20pt width compensation is
added to the reported desired size. This causes MAUI’s
HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt,
positioning the adjacent Label at X=114—safely outside the glass pill’s
visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width >
Bounds.Height, which is reliable because GetDesiredSize is invoked after
the layout transition completes.
A minor namespace update was also made: using System.Drawing → using
Microsoft.Maui.Graphics to resolve the Size return type without
ambiguity. RectangleF.Empty is explicitly qualified as
System.Drawing.RectangleF.Empty.

### Issues Fixed
Fixes #34273

### Key Technical Details

| Detail | Value |
|--------|-------|
| Affected platform | iOS only (`StepperHandler.iOS.cs`) |
| iOS version guard | `OperatingSystem.IsIOSVersionAtLeast(26)` |
| Orientation detection | `UIScreen.MainScreen.Bounds.Width >
Bounds.Height` |
| Compensation amount | 20pt (glass pill overflow measured empirically)
|
| MAUI API hook | `GetDesiredSize` override (called by
`HorizontalStackLayout` measurement) |
| Portrait behaviour | Unchanged — no 20pt is added in portrait |
| Public API addition | `override StepperHandler.GetDesiredSize(double,
double) -> Size` |

### Files Changed

| File | Change |
|------|--------|
| `src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs` | Add
`GetDesiredSize` override with iOS 26 landscape compensation (+24
lines); namespace fix `System.Drawing` → `Microsoft.Maui.Graphics` |
| `src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt` | Add public
API entry for `GetDesiredSize` override |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/77fee2cd-df2f-4057-a9f3-0af75ce5e0eb">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/86ceaacf-7b02-47cb-997a-1b8c71353064">)
|

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions bot pushed a commit that referenced this pull request Mar 22, 2026
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
On iOS 26 (Liquid Glass), a Stepper and Label placed in a
HorizontalStackLayout visually overlap after rotating the simulator to
landscape orientation. The overlap does not occur in portrait, nor on
iOS versions prior to 26.

### Root Cause
iOS 26 introduced a Liquid Glass design system where UIStepper renders a
glass pill that visually extends beyond the control’s logical frame on
the trailing (right) edge, with Layer.MasksToBounds = false. In
landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize,
AlignmentRectInsets) continue to report the logical size of 94×32pt and
are unaware of the glass overflow. MAUI’s layout engine relies on these
values and positions the adjacent Label at X=94, which falls inside the
visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no
compensation is required.

### Description of Change
GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on
iOS 26 or later in landscape orientation, a 20pt width compensation is
added to the reported desired size. This causes MAUI’s
HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt,
positioning the adjacent Label at X=114—safely outside the glass pill’s
visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width >
Bounds.Height, which is reliable because GetDesiredSize is invoked after
the layout transition completes.
A minor namespace update was also made: using System.Drawing → using
Microsoft.Maui.Graphics to resolve the Size return type without
ambiguity. RectangleF.Empty is explicitly qualified as
System.Drawing.RectangleF.Empty.

### Issues Fixed
Fixes #34273

### Key Technical Details

| Detail | Value |
|--------|-------|
| Affected platform | iOS only (`StepperHandler.iOS.cs`) |
| iOS version guard | `OperatingSystem.IsIOSVersionAtLeast(26)` |
| Orientation detection | `UIScreen.MainScreen.Bounds.Width >
Bounds.Height` |
| Compensation amount | 20pt (glass pill overflow measured empirically)
|
| MAUI API hook | `GetDesiredSize` override (called by
`HorizontalStackLayout` measurement) |
| Portrait behaviour | Unchanged — no 20pt is added in portrait |
| Public API addition | `override StepperHandler.GetDesiredSize(double,
double) -> Size` |

### Files Changed

| File | Change |
|------|--------|
| `src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs` | Add
`GetDesiredSize` override with iOS 26 landscape compensation (+24
lines); namespace fix `System.Drawing` → `Microsoft.Maui.Graphics` |
| `src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt` | Add public
API entry for `GetDesiredSize` override |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/77fee2cd-df2f-4057-a9f3-0af75ce5e0eb">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/86ceaacf-7b02-47cb-997a-1b8c71353064">)
|

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PureWeen added a commit that referenced this pull request Mar 24, 2026
## What's Coming

.NET MAUI inflight/candidate introduces significant improvements across
all platforms with focus on quality, performance, and developer
experience. This release includes 66 commits with various improvements,
bug fixes, and enhancements.


## Activityindicator
- [Android] Implemented material3 support for ActivityIndicator by
@Dhivya-SF4094 in #33481
  <details>
  <summary>🔧 Fixes</summary>

- [Implement material3 support for
ActivityIndicator](#33479)
  </details>

- [iOS] Fix: ActivityIndicator IsRunning ignores IsVisible when set to
true by @bhavanesh2001 in #28983
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] [ActivityIndicator] `IsRunning` ignores `IsVisible` when set to
`true`](#28968)
  </details>

## Button
- [iOS] Button RTL text and image overlap - fix by @kubaflo in
#29041

## Checkbox
- [iOS/MacCatalyst] Fix CheckBox foreground color not resetting when set
to null by @Ahamed-Ali in #34284
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Color of the checkBox control is not properly worked on dynamic
scenarios](#34278)
  </details>

## CollectionView
- [iOS] Fix: CollectionView does not clear selection when SelectedItem
is set to null by @Tamilarasan-Paranthaman in
#30420
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView not being able to remove selected item highlight on
iOS](#30363)
- [[MAUI] Select items traces are
preserved](#26187)
  </details>

- [iOS] CV2 ItemsLayout update by @kubaflo in
#28675
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView CollectionViewHandler2 doesnt change ItemsLayout on
DataTrigger](#28656)
- [iOS CollectionView doesn't respect a change to ItemsLayout when using
Items2.CollectionViewHandler2](#31259)
  </details>

- [iOS][CV2] Fix CollectionView renders large empty space at bottom of
view by @devanathan-vaithiyanathan in
#31215
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] [MacCatalyst] CollectionView renders large empty space at
bottom of view](#17799)
- [[iOS/Mac] CollectionView2 EmptyView takes up large horizontal space
even when the content is
small](#33201)
  </details>

- [iOS] Fixed issue where group Header/Footer template was set to all
items when IsGrouped was true for an ObservableCollection by
@Tamilarasan-Paranthaman in #29144
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Group Header/Footer Repeated for All Items When IsGrouped is
True for ObservableCollection in
CollectionView](#29141)
  </details>

- [Android] Fix CollectionView selection crash with HeaderTemplate by
@NirmalKumarYuvaraj in #34275
  <details>
  <summary>🔧 Fixes</summary>

- [[Bug] [Android] System.ArgumentOutOfRangeException: Index was out of
range. Must be non-negative and less than the size of the collection.
Parameter name: index](#34247)
  </details>

## DateTimePicker
- [iOS] Fix TimePicker AM/PM frequently changes when the app is closed
and reopened by @devanathan-vaithiyanathan in
#31066
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] TimePicker AM/PM frequently changes when the app is closed and
reopened](#30837)
- [Maui 10 iOS TimePicker Strange Characters in place of
AM/PM](#33722)
  </details>

- Android TimePicker ignores 24 hour system setting when using Format
Property - fix by @kubaflo in #28797
  <details>
  <summary>🔧 Fixes</summary>

- [Android TimePicker ignores 24 hour system setting when using Format
Property](#28784)
  </details>

## Drawing
- [iOS, Mac, Windows] GraphicsView: Fix Background/BackgroundColor not
updating by @NirmalKumarYuvaraj in
#31254
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Mac, Windows] GraphicsView does not change the
Background/BackgroundColor](#31239)
  </details>

- [iOS] GraphicsView DrawString - fix by @kubaflo in
#26304
  <details>
  <summary>🔧 Fixes</summary>

- [DrawString not rendering in
iOS.](#24450)
- [GraphicsView DrawString not rendering in
iOS](#8486)
- [DrawString doesn't work on
maccatalyst](#4993)
  </details>

- [Android] - Fix Shadow Rendering For Transparent Fill, Stroke (Lines),
and Text on Shapes by @prakashKannanSf3972 in
#29528
  <details>
  <summary>🔧 Fixes</summary>

- [Ellipse Transparency Not Rendered When Drawing Arc Inside the Ellipse
Using GraphicsView on
Android](#29394)
  </details>

- Revert "[iOS, Mac, Windows] GraphicsView: Fix
Background/BackgroundColor not updating (#31254)" by @Ahamed-Ali via
@Copilot in #34508

## Entry
- [iOS 26] Fix Entry MaxLength not enforced due to new multi-range
delegate by @kubaflo in #32045
  <details>
  <summary>🔧 Fixes</summary>

- [iOS 26 - The MaxLength property value is not respected on an Entry
control.](#32016)
- [.NET MAUI Entry Maximum Length not working on iOS and
macOS](#33316)
  </details>

- [iOS] Fixed Entry with IsPassword toggling loses previously entered
text by @SubhikshaSf4851 in #30572
  <details>
  <summary>🔧 Fixes</summary>

- [Entry with IsPassword toggling loses previously entered text on iOS
when IsPassword is
re-enabled](#30085)
  </details>

## Essentials
- Fix for FilePicker PickMultipleAsync nullable reference type by
@SuthiYuvaraj in #33163
  <details>
  <summary>🔧 Fixes</summary>

- [FilePicker PickMultipleAsync nullable reference
type](#33114)
  </details>

- Replace deprecated NetworkReachability with NWPathMonitor on iOS/macOS
by @jfversluis via @Copilot in #32354
  <details>
  <summary>🔧 Fixes</summary>

- [NetworkReachability is obsolete on iOS/maccatalyst
17.4+](#32312)
- [Use NWPathMonitor on iOS for Essentials
Connectivity](#2574)
  </details>

## Essentials Connectivity
- Update Android Connectivity implementation to use modern APIs by
@jfversluis via @Copilot in #30348
  <details>
  <summary>🔧 Fixes</summary>

- [Update the Android Connectivity implementation to user modern
APIs](#30347)
  </details>

## Flyout
- [iOS] Fixed Flyout icon not updating when root page changes using
InsertPageBefore by @Vignesh-SF3580 in
#29924
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Flyout icon not replaced by back button when root page is
changed using
InsertPageBefore](#29921)
  </details>

## Flyoutpage
- [iOS] Flyout Items Not Displayed in RightToLeft FlowDirection in
Landscape - fix by @kubaflo in #26762
  <details>
  <summary>🔧 Fixes</summary>

- [Flyout Items Not Displayed in RightToLeft FlowDirection on iOS in
Landscape Orientation and Hamburger Icon Positioned
Incorrectly](#26726)
  </details>

## Image
- [Android] Implemented Material3 support for Image by @Dhivya-SF4094 in
#33661
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 support for
Image](#33660)
  </details>

## Keyboard
- [iOS] Fix gap at top of view after rotating device while Entry
keyboard is visible by @praveenkumarkarunanithi in
#34328
  <details>
  <summary>🔧 Fixes</summary>

- [Focusing and entering texts on entry control causes a gap at the top
after rotating simulator.](#33407)
  </details>

## Label
- [Android] Support for images inside HTML label by @kubaflo in
#21679
  <details>
  <summary>🔧 Fixes</summary>

- [Label with HTML TextType does not display images on
Android](#21044)
  </details>

- [fix] ContentLabel Moved to a nested class to prevent CS0122 in
external source generators by @SubhikshaSf4851 in
#34514
  <details>
  <summary>🔧 Fixes</summary>

- [[MAUI] Building Maui App with sample content results CS0122
errors.](#34512)
  </details>

## Layout
- Optimize ordering of children in Flex layout by @symbiogenesis in
#21961

- [Android] Fix control size properties not available during Loaded
event by @Vignesh-SF3580 in #31590
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView on Android does not provide height, width, logical
children once loaded, works fine on
Windows](#14364)
- [Control's Loaded event invokes before calling its measure override
method.](#14160)
  </details>

## Mediapicker
- [iOS/Android] MediaPicker: Fix image orientation when RotateImage=true
by @michalpobuta in #33892
  <details>
  <summary>🔧 Fixes</summary>

- [MediaPicker.PickPhotosAsync does not preserve image
orientation](#32650)
  </details>

## Modal
- [Windows] Fix modal page keyboard focus not shifting to newly opened
modal by @jfversluis in #34212
  <details>
  <summary>🔧 Fixes</summary>

- [Keyboard focus does not shift to a newly opened modal page: Pressing
enter clicks the button on the page beneath the modal
page](#22938)
  </details>

## Navigation
- [iOS26] Apply view margins in title view by @kubaflo in
#32205
  <details>
  <summary>🔧 Fixes</summary>

- [NavigationPage TitleView iOS
26](#32200)
  </details>

- [iOS] System.NullReferenceException at
NavigationRenderer.SetStatusBarStyle() by @kubaflo in
#29564
  <details>
  <summary>🔧 Fixes</summary>

- [System.NullReferenceException at
NavigationRenderer.SetStatusBarStyle()](#29535)
  </details>

- [iOS 26] Fix back button color not applied for NavigationPage by
@Shalini-Ashokan in #34326
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Color not applied to the Back button text or image on iOS
26](#33966)
  </details>

## Picker
- Fix Picker layout on Mac Catalyst 26+ by @kubaflo in
#33146
  <details>
  <summary>🔧 Fixes</summary>

- [[MacOS 26] Text on picker options are not centered on macOS
26.1](#33229)
  </details>

## Progressbar
- [Android] Implemented Material3 support for ProgressBar by
@SyedAbdulAzeemSF4852 in #33926
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 support for
Progressbar](#33925)
  </details>

## RadioButton
- [iOS, Mac] Fix for RadioButton TextColor for plain Content not working
by @HarishwaranVijayakumar in #31940
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButton: TextColor for plain Content not working on
iOS](#18011)
  </details>

- [All Platforms] Fix RadioButton warning when ControlTemplate is set
with View content by @kubaflo in
#33839
  <details>
  <summary>🔧 Fixes</summary>

- [Seeking clarification on RadioButton + ControlTemplate + Content
documentation](#33829)
  </details>

- Visual state change for disabled RadioButton by @kubaflo in
#23471
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButton disabled UI issue -
iOS](#18668)
  </details>

## SafeArea
- [Android] Fix for TabbedPage BottomNavigation BarBackgroundColor not
extending to system navigation bar by @praveenkumarkarunanithi in
#33428
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] TabbedPage BottomNavigation BarBackgroundColor does not
extend to system navigation bar area in Edge-to-Edge
mode](#33344)
  </details>

## ScrollView
- [Android] ScrollView: Fix HorizontalScrollBarVisibility not updating
immediately at runtime by @SubhikshaSf4851 in
#33528
  <details>
  <summary>🔧 Fixes</summary>

- [Runtime Scrollbar visibility not updating correctly on Android and
macOS platforms.](#33400)
  </details>

- Fixed crash when calling ItemsView.ScrollTo on unloaded CollectionView
by @kubaflo in #25444
  <details>
  <summary>🔧 Fixes</summary>

- [App crashes when calling ItemsView.ScrollTo on unloaded
CollectionView](#23014)
  </details>

## Shell
- [Shell] Update logic for iOS large title display in ShellItemRenderer
by @kubaflo in #33246

- [iOS][Shell] Fix navigation lifecycle and back button for More tab (>5
tabs) by @kubaflo in #27932
  <details>
  <summary>🔧 Fixes</summary>

- [OnAppearing and OnNavigatedTo does not work when using extended
Tabbar (tabbar with more than 5 tabs) on
IOS.](#27799)
- [Shell.BackButtonBehavior does not work when using extended Tabbar
(tabbar with more than 5 tabs)on
IOS.](#27800)
- [Shell TabBar More button causes ViewModel command binding
disconnection on back
navigation](#30862)
- [Content page onappearing not firing if tabs are on the more tab on
IOS](#31166)
  </details>

- [iOS 26] Fix tab bar ghosting when navigating from modal to tabbed
Shell content by @SubhikshaSf4851 in
#34254
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Tab bar ghosting issue on iOS 26 (liquid
glass)](#34143)
  </details>

- Fix for Shell tab visibility not updating when navigating back
multiple pages by @BagavathiPerumal in
#34403
  <details>
  <summary>🔧 Fixes</summary>

- [Changing Shell Tab Visibility when navigating back multiple pages
ignores Shell Tab
Visibility](#33351)
  </details>

- [iOS/Mac] Fixed OnBackButtonPressed not firing for Shell Navigation
Bar Button by @Dhivya-SF4094 in
#34401
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] OnBackButtonPressed not firing for Shell Navigation Bar
button](#34190)
  </details>

## Slider
- [iOS] Fix for Slider ThumbImageSource is not centered properly on iOS
26 by @HarishwaranVijayakumar in
#34019
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS 26] Slider ThumbImageSource is not centered
properly](#33967)
  </details>

- [Android] Fix improper rendering of ThumbimageSource in Slider by
@NirmalKumarYuvaraj in #34064
  <details>
  <summary>🔧 Fixes</summary>

- [[Slider] MAUI Slider thumb image is big on
android](#13258)
  </details>

## Stepper
- [iOS] Fix Stepper layout overlap in landscape on iOS 26 by
@Vignesh-SF3580 in #34325
  <details>
  <summary>🔧 Fixes</summary>

- [[.NET10] D10 - Customize cursor position - Rotating simulator makes
the button and label
overlap](#34273)
  </details>

## SwipeView
- [iOS] SwipeView: Honor FontImageSource.Color in SwipeItem icon by
@kubaflo in #27389
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] SwipeView: SwipeItem.IconImageSource.FontImageSource color
value not honored](#27377)
  </details>

## Switch
- [Android] Fix Switch thumb shadow missing when ThumbColor is set by
@Shalini-Ashokan in #33960
  <details>
  <summary>🔧 Fixes</summary>

- [Android Switch Control Thumb
Shadow](#19676)
  </details>

## Toolbar
- [iOS/Mac Catalyst 26] Fix Shell.ForegroundColor not applied to
ToolbarItems by @SyedAbdulAzeemSF4852 in
#34085
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS26] Shell.ForegroundColor is not applied to
ToolbarItems](#34083)
  </details>

- [Android] VoiceOver on Toolbar Item by @kubaflo in
#29596
  <details>
  <summary>🔧 Fixes</summary>

- [VoiceOver on Toolbar
Item](#29573)
- [SemanticProperties do not work on
ToolbarItems](#23623)
  </details>


<details>
<summary>🧪 Testing (11)</summary>

- [Testing] Additional Feature Matrix Test Cases for CollectionView by
@TamilarasanSF4853 in #32432
- [Testing] Feature Matrix UITest Cases for VisualStateManager by
@LogishaSelvarajSF4525 in #34146
- [Testing] Feature Matrix UITest Cases for Clip by @TamilarasanSF4853
in #34121
- [Testing] Feature matrix UITest Cases for Map Control by
@HarishKumarSF4517 in #31656
- [Testing] Feature matrix UITest Cases for Visual Transform Control by
@HarishKumarSF4517 in #32799
- [Testing] Feature Matrix UITest Cases for Shell Pages by
@NafeelaNazhir in #33945
- [Testing] Feature Matrix UITest Cases for Triggers by
@HarishKumarSF4517 in #34152
- [Testing] Refactoring Feature Matrix UITest Cases for CheckBox Control
by @LogishaSelvarajSF4525 in #34283
- Resolve UI test Build Sample failures - Candidate March 16 by
@Ahamed-Ali in #34442
- Fix the failures in the Candidate branch- March 16 by @Ahamed-Ali in
#34453
  <details>
  <summary>🔧 Fixes</summary>

  - [March 16th, Candidate](#34437)
  </details>
- Fixed the iOS 18.5 Candidate failures (March 16,2026) by @Ahamed-Ali
in #34593
  <details>
  <summary>🔧 Fixes</summary>

  - [March 16th, Candidate](#34437)
  </details>

</details>

<details>
<summary>📦 Other (2)</summary>

- Fixed candidate test failures caused by PR #33428. by @Ahamed-Ali in
#34515
  <details>
  <summary>🔧 Fixes</summary>

- [[.NET10] On Android, there's a big space at the top for I, M and N2 &
N3](#34509)
  </details>
- Revert "[iOS] Button RTL text and image overlap - fix (#29041)" in
b0497af

</details>

<details>
<summary>📝 Issue References</summary>

Fixes #2574, Fixes #4993, Fixes #8486, Fixes #13258, Fixes #14160, Fixes
#14364, Fixes #17799, Fixes #18011, Fixes #18668, Fixes #19676, Fixes
#21044, Fixes #22938, Fixes #23014, Fixes #23623, Fixes #24450, Fixes
#26187, Fixes #26726, Fixes #27377, Fixes #27799, Fixes #27800, Fixes
#28656, Fixes #28784, Fixes #28968, Fixes #29141, Fixes #29394, Fixes
#29535, Fixes #29573, Fixes #29921, Fixes #30085, Fixes #30347, Fixes
#30363, Fixes #30837, Fixes #30862, Fixes #31166, Fixes #31239, Fixes
#31259, Fixes #32016, Fixes #32200, Fixes #32312, Fixes #32650, Fixes
#33114, Fixes #33201, Fixes #33229, Fixes #33316, Fixes #33344, Fixes
#33351, Fixes #33400, Fixes #33407, Fixes #33479, Fixes #33660, Fixes
#33722, Fixes #33829, Fixes #33925, Fixes #33966, Fixes #33967, Fixes
#34083, Fixes #34143, Fixes #34190, Fixes #34247, Fixes #34273, Fixes
#34278, Fixes #34437, Fixes #34509, Fixes #34512

</details>

**Full Changelog**:
main...inflight/candidate
KarthikRajaKalaimani pushed a commit to KarthikRajaKalaimani/maui that referenced this pull request Mar 30, 2026
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
On iOS 26 (Liquid Glass), a Stepper and Label placed in a
HorizontalStackLayout visually overlap after rotating the simulator to
landscape orientation. The overlap does not occur in portrait, nor on
iOS versions prior to 26.

### Root Cause
iOS 26 introduced a Liquid Glass design system where UIStepper renders a
glass pill that visually extends beyond the control’s logical frame on
the trailing (right) edge, with Layer.MasksToBounds = false. In
landscape orientation, this overflow is approximately 18–20pt.
All UIKit measurement APIs (SizeThatFits, IntrinsicContentSize,
AlignmentRectInsets) continue to report the logical size of 94×32pt and
are unaware of the glass overflow. MAUI’s layout engine relies on these
values and positions the adjacent Label at X=94, which falls inside the
visible glass pill area.
In portrait orientation, the glass overflow is negligible, so no
compensation is required.

### Description of Change
GetDesiredSize is overridden in StepperHandler.iOS.cs. When running on
iOS 26 or later in landscape orientation, a 20pt width compensation is
added to the reported desired size. This causes MAUI’s
HorizontalStackLayout to allocate 114pt for the Stepper instead of 94pt,
positioning the adjacent Label at X=114—safely outside the glass pill’s
visual extent.
Orientation is detected by comparing UIScreen.MainScreen.Bounds.Width >
Bounds.Height, which is reliable because GetDesiredSize is invoked after
the layout transition completes.
A minor namespace update was also made: using System.Drawing → using
Microsoft.Maui.Graphics to resolve the Size return type without
ambiguity. RectangleF.Empty is explicitly qualified as
System.Drawing.RectangleF.Empty.

### Issues Fixed
Fixes dotnet#34273

### Key Technical Details

| Detail | Value |
|--------|-------|
| Affected platform | iOS only (`StepperHandler.iOS.cs`) |
| iOS version guard | `OperatingSystem.IsIOSVersionAtLeast(26)` |
| Orientation detection | `UIScreen.MainScreen.Bounds.Width >
Bounds.Height` |
| Compensation amount | 20pt (glass pill overflow measured empirically)
|
| MAUI API hook | `GetDesiredSize` override (called by
`HorizontalStackLayout` measurement) |
| Portrait behaviour | Unchanged — no 20pt is added in portrait |
| Public API addition | `override StepperHandler.GetDesiredSize(double,
double) -> Size` |

### Files Changed

| File | Change |
|------|--------|
| `src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs` | Add
`GetDesiredSize` override with iOS 26 landscape compensation (+24
lines); namespace fix `System.Drawing` → `Microsoft.Maui.Graphics` |
| `src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt` | Add public
API entry for `GetDesiredSize` override |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/77fee2cd-df2f-4057-a9f3-0af75ce5e0eb">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/86ceaacf-7b02-47cb-997a-1b8c71353064">)
|

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-stepper Stepper community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) version/iOS-26

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[.NET10] D10 - Customize cursor position - Rotating simulator makes the button and label overlap

5 participants