[iOS] Fix Stepper layout overlap in landscape on iOS 26#34325
[iOS] Fix Stepper layout overlap in landscape on iOS 26#34325kubaflo merged 5 commits intodotnet:inflight/currentfrom
Conversation
…ulator makes the button and label overlap
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34325Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34325" |
There was a problem hiding this comment.
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.GetDesiredSizeon iOS to add a landscape-only width compensation on iOS 26+. - Add PublicAPI entries for the new
StepperHandler.GetDesiredSizeoverride (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. |
| #nullable enable | ||
| override Microsoft.Maui.Handlers.StepperHandler.GetDesiredSize(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size |
There was a problem hiding this comment.
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).
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Added snapshots. ·
|
| File | Type | Change |
|---|---|---|
src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs |
Fix | Override GetDesiredSize with iOS 26 landscape compensation (+38 lines); namespace System.Drawing → Microsoft.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:
- Spelling issues in HostApp test page (
Issue34273.cs): "strong" → "string", "pree" → "press", "The tests fails" → "The test fails", unclosed(NOTE:parenthesis - Comment inaccuracy: PR says "Mac displays are always landscape" — but MacCatalyst apps can run in resizable windows
net-maccatalyst/PublicAPI.Unshipped.txtwas changed but not mentioned in the PR description
| File:Line | Reviewer Says | Status |
|---|---|---|
Issue34273.cs:52 |
"pree" should be "press" | |
Issue34273.cs:52 |
"strong" should be "string", unclosed (NOTE: |
|
Issue34273.cs:49 |
"The tests fails" should be "The test fails" | |
StepperHandler.iOS.cs:39 |
"Mac displays are always landscape" comment is inaccurate | |
PublicAPI net-maccatalyst:2 |
MacCatalyst API entry not mentioned in PR description |
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 Session — Added 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 Session — Added 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 fix — GetDesiredSize 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):
- Inaccurate comment: "Mac displays are always landscape" — MacCatalyst supports resizable windows
- Spelling errors in HostApp test page (already flagged by Copilot auto-reviewer)
- MacCatalyst PublicAPI change not mentioned in PR description table
📋 Report — Final Recommendation
📝 Review Session — Added 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 —
GetDesiredSizeis 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 = 20with 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:
- Add
net-maccatalyst/PublicAPI.Unshipped.txtto 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.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 (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.Drawing → Microsoft.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
GetDesiredSizeoverride correctly callsbase.GetDesiredSizefirst, 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()returnsfalseon 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
GetDesiredSizeexplain 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-iosandnet-maccatalyst. - Namespace change is correct. Switching from
System.DrawingtoMicrosoft.Maui.GraphicsforSizeand qualifyingRectangleF.EmptyasSystem.Drawing.RectangleF.Emptyavoids 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.
- 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>
> [!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>
> [!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>
> [!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>
> [!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>
> [!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>
## 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
> [!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>
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
StepperHandler.iOS.cs)OperatingSystem.IsIOSVersionAtLeast(26)UIScreen.MainScreen.Bounds.Width > Bounds.HeightGetDesiredSizeoverride (called byHorizontalStackLayoutmeasurement)override StepperHandler.GetDesiredSize(double, double) -> SizeFiles Changed
src/Core/src/Handlers/Stepper/StepperHandler.iOS.csGetDesiredSizeoverride with iOS 26 landscape compensation (+24 lines); namespace fixSystem.Drawing→Microsoft.Maui.Graphicssrc/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txtGetDesiredSizeoverrideScreenshots
34273BeforeFix.mov
34273AfterFix.mov