Skip to content

[iOS] Fix stale bottom safe area after changing SafeAreaEdges with keyboard open#35083

Merged
kubaflo merged 2 commits into
dotnet:inflight/currentfrom
praveenkumarkarunanithi:Fix-34846
Apr 26, 2026
Merged

[iOS] Fix stale bottom safe area after changing SafeAreaEdges with keyboard open#35083
kubaflo merged 2 commits into
dotnet:inflight/currentfrom
praveenkumarkarunanithi:Fix-34846

Conversation

@praveenkumarkarunanithi

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!

Root Cause

When SafeAreaEdges changes from a mode that includes SoftInput (e.g., All) to one that does not (e.g., Container), the view unsubscribes from iOS keyboard notifications. However, the keyboard state (_isKeyboardShowing, _keyboardFrame) was not cleared. If the keyboard was open during unsubscription and later dismissed, the OnKeyboardWillHide event is never received. When switching back to a SoftInput mode, the view re-subscribes with stale state, applying incorrect bottom padding equal to the old keyboard height instead of the home indicator inset.

Description of Change

Added state cleanup in UnsubscribeFromKeyboardNotifications in MauiView.cs. When unsubscribing, if the keyboard was previously visible, the method now clears the keyboard state, invalidates the safe area, and triggers a layout update. This prevents stale keyboard state from persisting across subscribe/unsubscribe cycles while preserving existing behavior in all other scenarios.

Also added a test in Issue28986_ContentPage that reproduces the exact sequence: switch to All, open keyboard, change to Container, dismiss keyboard, switch back to All, and verify the layout returns to baseline without phantom padding.

Issues Fixed

Fixes #34846

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Screenshots

Before Issue Fix After Issue Fix
BeforeFix.33.mov
AfterFix.40.mov

@github-actions

Copy link
Copy Markdown
Contributor

🚀 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 -- 35083

Or

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

@praveenkumarkarunanithi praveenkumarkarunanithi added platform/ios area-safearea Issues/PRs that have to do with the SafeArea functionality labels Apr 22, 2026
@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Apr 22, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review April 22, 2026 10:58
Copilot AI review requested due to automatic review settings April 22, 2026 10:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 safe-area regression where bottom padding can remain “stuck” after SafeAreaEdges is changed while the keyboard is open, by resetting keyboard-related safe-area state when unsubscribing from keyboard notifications and adding a UI test that reproduces the reported sequence.

Changes:

  • Clear keyboard state during UnsubscribeFromKeyboardNotifications() to prevent stale _isKeyboardShowing / _keyboardFrame from affecting later safe area calculations.
  • Refactor keyboard-hide handling to reuse a shared ClearKeyboardState() helper.
  • Add a UITest that toggles SafeAreaEdges, shows/dismisses the keyboard, and verifies the layout returns to baseline without extra whitespace.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Core/src/Platform/iOS/MauiView.cs Resets keyboard state on unsubscribe and centralizes keyboard-hide cleanup to avoid stale safe-area padding.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_ContentPage.cs Adds a regression test covering the “toggle edges while keyboard open, then dismiss, then toggle back” sequence from the issue.

Comment on lines +327 to +332
// Clear stale keyboard state so that re-subscribing later doesn't
// pick up a phantom keyboard frame from a previous session (#34846).
if (_isKeyboardShowing)
{
ClearKeyboardState();
}

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

Clearing keyboard state during UnsubscribeFromKeyboardNotifications() fixes the stale-padding case when the keyboard is dismissed while unsubscribed, but it can regress the opposite flow: if SafeAreaEdges toggles back to a SoftInput/All mode while the keyboard is still visible, the view will re-subscribe without receiving a new WillShow notification, leaving _isKeyboardShowing false and _keyboardFrame empty, so no keyboard padding will be applied until the keyboard changes again. Consider keeping keyboard observers active until WillHide is observed (then unsubscribe), or keep the last keyboard frame and rehydrate _isKeyboardShowing on subscribe when a first responder exists.

Copilot uses AI. Check for mistakes.
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 22, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please review the ai's summary?

@dotnet dotnet deleted a comment from MauiBot Apr 25, 2026
@MauiBot

MauiBot commented Apr 26, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI Summary

👋 @praveenkumarkarunanithi — new AI review results are available. Please review the latest session below.

📊 Review Session6b178bc · fix update · 2026-04-26 02:26 UTC
🚦 Gate — Test Before & After Fix

Gate tests FAIL without fix, PASS with fix.PASSED
Platform: ios


🧪 UI Tests — Category Detection

Detected UI test categories: SafeAreaEdges,ViewBaseTests


🔍 Pre-Flight — Context & Validation

Issue: #34846 - [iOS] ContentPage bottom has white space after changing SafeAreaEdges while keyboard is open
PR: #35083 - [iOS] Fix stale bottom safe area after changing SafeAreaEdges with keyboard open
Platforms Affected: iOS (fix in MauiView.cs also covers macCatalyst compilation-wise; macCatalyst test not added)
Files Changed: 1 implementation (src/Core/src/Platform/iOS/MauiView.cs), 1 test (src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986_ContentPage.cs)

Key Findings

  • Bug: When SafeAreaEdges changes from All/SoftInput-inclusive to Container/non-SoftInput while keyboard is open, the view unsubscribes from keyboard notifications without clearing _isKeyboardShowing / _keyboardFrame. On re-subscribe, stale state causes phantom bottom padding equal to old keyboard height.
  • Fix: UnsubscribeFromKeyboardNotifications() now calls the new ClearKeyboardState() helper (guarded by if (_isKeyboardShowing)) to reset both fields, invalidate safe area, and trigger layout.
  • Refactor: OnKeyboardWillHide is simplified to call ClearKeyboardState() — identical behaviour, no regression.
  • Prior Copilot inline review noted reverse-edge-case concern (keyboard still visible when re-subscribing → no WillShow fires → padding missing). This is a legitimate concern but not addressed by this PR.
  • Reviewer kubaflo requested changes asking the author to review the AI's summary.

Code Review Summary

Verdict: LGTM
Confidence: high
Errors: 0 | Warnings: 0 | Suggestions: 2

Key code review findings:

  • 💡 macCatalyst coverage gap — MauiView.cs compiles for macCatalyst too, but new test is #if IOS || ANDROID only
  • 💡 No WaitForElement between GridSetContainerButton tap and DismissKeyboard() — could be theoretically flaky on slow CI

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #35083 Clear _isKeyboardShowing/_keyboardFrame on unsubscribe (via ClearKeyboardState()); refactor OnKeyboardWillHide to call same helper ✅ PASSED (Gate) MauiView.cs, test file Original PR

🔬 Code Review — Deep Analysis

Code Review — PR #35083

Independent Assessment

What this changes: MauiView.cs gets a new private ClearKeyboardState() helper extracted from OnKeyboardWillHide. That helper is then called inside UnsubscribeFromKeyboardNotifications() when _isKeyboardShowing is true at unsubscription time. A new UI test exercises the exact subscribe/change-edges/dismiss/re-subscribe cycle.

Inferred motivation: Something causes keyboard observer state (_isKeyboardShowing, _keyboardFrame) to go stale when the view unsubscribes while the keyboard is open. On re-subscription the stale frame produces phantom bottom padding.


Reconciliation with PR Narrative

Author claims: When SafeAreaEdges switches from a SoftInput-inclusive mode (e.g. All) to a non-SoftInput mode (e.g. Container) while the keyboard is visible, the view unsubscribes from iOS keyboard notifications without resetting _isKeyboardShowing/_keyboardFrame. The subsequent KeyboardWillHide event is never received. Switching back to All re-subscribes with stale state, applying an incorrect bottom padding equal to the old keyboard height.

Agreement/disagreement: The root cause analysis matches the code exactly. SubscribeToKeyboardNotifications() guards against double-subscription with an early return, so re-subscribing on a view that still has _isKeyboardShowing = true was the only path to the phantom padding. The fix is placed at the right callsite.


Findings

💡 Suggestion — macCatalyst coverage gap

The fix lives in MauiView.cs, which compiles for both iOS and macCatalyst (.ios.cs convention). The new test is #if IOS || ANDROID, so macCatalyst never exercises this path. macCatalyst external keyboards can open/close and UIKeyboard.WillHide notifications fire there too. If the same SafeAreaEdges + keyboard cycle is reproducible on Mac Catalyst, a separate macCatalyst UI test (or extending the #if to include MACCATALYST) would close the coverage gap.

💡 Suggestion — No wait between GridSetContainerButton and DismissKeyboard()

In SafeAreaNoWhiteSpaceAfterKeyboardDismissAndEdgeToggle, App.Tap("GridSetContainerButton") triggers UpdateKeyboardSubscriptionUnsubscribeFromKeyboardNotificationsClearKeyboardStateSetNeedsLayout. The layout pass is async; App.DismissKeyboard() fires immediately after without a RetryAssert. In practice this works because the Appium tap is synchronous and the main-thread layout is fast, but if this test becomes flaky on slower CI devices, inserting a App.WaitForElement("ContentGrid") between the two taps would make the sequencing deterministic.


Devil's Advocate

Challenge my approval:

  • Could ClearKeyboardState() calling SetNeedsLayout() inside UnsubscribeFromKeyboardNotifications() cause an extra layout pass in the normal (keyboard-not-showing) unsubscription path? No — the guard if (_isKeyboardShowing) ensures this only fires when the keyboard was actually open.
  • Could there be a window where OnKeyboardWillHide fires between the observer removal and the _isKeyboardShowing check? iOS notifications are dispatched on the main thread; since UnsubscribeFromKeyboardNotifications also runs on the main thread, there is no race.
  • Does the refactoring change OnKeyboardWillHide behavior? The extracted ClearKeyboardState() body is bit-for-bit identical to the old OnKeyboardWillHide body. Behaviour is preserved.

Challenge my suggestions:

  • The macCatalyst gap is real but low-priority: hardware keyboard interaction on macCatalyst is a different UX than an on-screen keyboard dismiss, and CI for macCatalyst SafeArea tests is expensive. It is reasonable to defer to a follow-up.
  • The wait concern in the test is theoretical; all five existing tests in the same class use the same pattern without flake reports.

Verdict: LGTM

Confidence: high

Summary: The fix is minimal, correctly placed, and addresses the root cause without touching unrelated code paths. The ClearKeyboardState() extraction is a clean refactor with no behavioral change to OnKeyboardWillHide. All CI checks pass. The two observations above are low-risk suggestions, not blockers.


🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Guard read-site with IsSubscribedToKeyboardNotifications property; stale state ignored when unsubscribed; unconditional clear on BLOCKED 1 file Appium/XCTest timeout (OneTimeSetUp not a code failure 60s) unsubscribe
2 try-fix (claude-sonnet-4.6) Drain-mode WillHide keep WillHide observer alive when unsubscribing while keyboard is showing; self-removes on WillHide fire; also fixes reverse edge case PASS 1 file More complex lifecycle; handles keyboard-still-visible re-subscribe case
3 try-fix (gpt-5.3-codex) Re-hydrate keyboard state on subscribe from / PASS 1 file Depends on global keyboard tracker; handles both stale and still-visible cases
4 try-fix (gpt-5.4) Subscription-versioned keyboard state stamped with subscription generation, stale state self-invalidates PASS 1 file Most complex approach; versioning overhead
5 try-fix (claude-opus-4.6 cross-poll) Always-subscribed observers while in gate keyboard padding at read-site with window PASS 1 file Eliminates problem class; more complex subscription model
6 try-fix (claude-sonnet-4.6 cross-poll) UIKeyboardLayoutGuide live compute overlap from live guide FAIL 1 file Guide requires active constraints; always CGRect.Zero without them frame
PR PR #35083 Clear / on unsubscribe (conditional ) via helper; refactor to reuse same helper PASSED (Gate) 2 files Original minimal and targeted

Cross-Pollination

Model Round New Ideas? Details
ran as attempt 5
ran as attempt 6
covered by attempt 6
gpt-5.4 2 N/A (not queried merged with round 2)
claude-opus-4.6 3 Yes First-responder ground-truth check at read- redundant given 4 passing alternatives
gpt-5.4 3 Yes UIKeyboardWillChangeFrame-driven more complex, no clear advantage

Exhausted: Yes (3 cross-poll rounds; remaining ideas add complexity without quality improvement for this specific bug)
Selected Fix: PRs Simplest (10 net lines), correctly targeted at root cause, minimal blast radius, Gate PASSED, code review LGTM (high confidence). Alternatives 5 all pass but add unnecessary complexity.2 fix


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #34846, PR #35083, 2 files changed (1 impl + 1 test), prior Copilot inline review imported
Code Review LGTM (high) 0 errors, 0 warnings, 2 low-priority suggestions
Gate ✅ PASSED ios — tests FAIL without fix, PASS with fix
Try-Fix ✅ COMPLETE 6 attempts: 1 blocked (infra), 4 passing alternatives, 1 failed; 3 cross-poll rounds exhausted
Report ✅ COMPLETE

Code Review Impact on Try-Fix

Code review returned LGTM with zero errors and two low-priority suggestions (macCatalyst test coverage gap; minor sequencing concern in test). Since there were no ❌ errors to target, the hints field in try-fix prompts focused on the reverse-edge-case concern noted by the prior Copilot inline reviewer (keyboard still visible when re-subscribing). This guided attempts 2 and 3 to explicitly address that edge case with drain-mode and re-hydration approaches. None of the error-free code review findings changed the final recommendation.

Summary

PR #35083 fixes a stale keyboard state bug on iOS where changing SafeAreaEdges from All/SoftInput to Container/non-SoftInput while the keyboard is open causes phantom bottom whitespace. The PR's fix is minimal (10 net lines), correctly targeted, and passes both the Gate and 4 of 5 independently-explored alternative approaches. The code review found no correctness issues. Multi-model try-fix exploration confirmed the PR's approach is the simplest of all passing candidates.

Root Cause

When UnsubscribeFromKeyboardNotifications() is called with _isKeyboardShowing = true (i.e., keyboard was open when SafeAreaEdges changed to a non-SoftInput mode), the view stops receiving UIKeyboard.WillHideNotification. The cached state _isKeyboardShowing = true and _keyboardFrame (non-empty) persist. On re-subscribing to SoftInput mode, SubscribeToKeyboardNotifications() guards against double-subscription but does not re-hydrate state — it just adds observers for future notifications. GetAdjustedSafeAreaInsets() reads the stale _isKeyboardShowing = true and applies phantom bottom padding.

Fix Quality

The PR's fix is excellent quality:

  • Targeted: adds one if (_isKeyboardShowing) guard block in UnsubscribeFromKeyboardNotifications() calling ClearKeyboardState()
  • Clean refactor: OnKeyboardWillHide is simplified to a one-liner calling ClearKeyboardState() — identical behavior, reduced duplication
  • No regression risk: the guard ensures SetNeedsLayout() is only called when the keyboard was actually showing at unsubscription time
  • Well-tested: new SafeAreaNoWhiteSpaceAfterKeyboardDismissAndEdgeToggle test reproduces exact reported sequence
  • Prior Copilot review concern about reverse edge case (keyboard still visible when re-subscribing): this is a separate scenario not reported as a bug, and this PR does not make it worse — it was already unhandled before this change. Multiple try-fix alternatives (drain-mode, re-hydration) that address this were more complex without being demonstrably better for the reported bug.

@MauiBot MauiBot added s/agent-approved AI agent recommends approval - PR fix is correct and optimal and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels Apr 26, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current April 26, 2026 11:02
@kubaflo kubaflo merged commit 3cd77e7 into dotnet:inflight/current Apr 26, 2026
36 checks passed
@github-actions github-actions Bot added this to the .NET 10 SR7 milestone Apr 26, 2026
PureWeen pushed a commit that referenced this pull request Apr 28, 2026
…yboard open (#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes #34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
PureWeen pushed a commit that referenced this pull request Apr 29, 2026
…yboard open (#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes #34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
github-actions Bot pushed a commit that referenced this pull request May 6, 2026
…yboard open (#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes #34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
kubaflo pushed a commit that referenced this pull request May 7, 2026
…yboardOpen test failure in May 4th Candidate (#35307)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details
PR #35083 fixed the stale safe area issue when switching from All to
Container while the keyboard was open.
But that change introduced a regression for the opposite runtime flow.
 
On iOS, when switching from Container to SoftInput while the keyboard is
already open, MauiView may not receive a new keyboard show event.
Because the keyboard state was cleared during unsubscribe, the view can
miss the current keyboard state and fail to apply the expected
keyboard-related bottom inset.

### Description of Change

<!-- Enter description of the fix in this section -->
This change updates iOS keyboard handling in MauiView.cs:312. When
switching to SoftInput while the keyboard is already open, it restores
keyboard state immediately and refreshes layout, so safe area updates
correctly.

### Issues Fixed
* ValidateKeyboardRuntime_SwitchContainerToSoftInput_WhileKeyboardOpen
@kubaflo kubaflo added the s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates label May 20, 2026
github-actions Bot pushed a commit that referenced this pull request May 25, 2026
…yboard open (#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes #34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
github-actions Bot pushed a commit that referenced this pull request May 25, 2026
…yboardOpen test failure in May 4th Candidate (#35307)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details
PR #35083 fixed the stale safe area issue when switching from All to
Container while the keyboard was open.
But that change introduced a regression for the opposite runtime flow.
 
On iOS, when switching from Container to SoftInput while the keyboard is
already open, MauiView may not receive a new keyboard show event.
Because the keyboard state was cleared during unsubscribe, the view can
miss the current keyboard state and fail to apply the expected
keyboard-related bottom inset.

### Description of Change

<!-- Enter description of the fix in this section -->
This change updates iOS keyboard handling in MauiView.cs:312. When
switching to SoftInput while the keyboard is already open, it restores
keyboard state immediately and refreshes layout, so safe area updates
correctly.

### Issues Fixed
* ValidateKeyboardRuntime_SwitchContainerToSoftInput_WhileKeyboardOpen
devanathan-vaithiyanathan pushed a commit to devanathan-vaithiyanathan/maui that referenced this pull request Jun 1, 2026
…yboard open (dotnet#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes dotnet#34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
@PureWeen PureWeen mentioned this pull request Jun 2, 2026
PureWeen added a commit that referenced this pull request Jun 2, 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 85 commits with various improvements,
bug fixes, and enhancements.


## Button
- [Android, iOS] Button: Fix VisualState properties not restored when
leaving custom state by @BagavathiPerumal in
#33346
  <details>
  <summary>🔧 Fixes</summary>

- [Button VisualStates do not
work](#19690)
  </details>

## CollectionView
- Fix CollectionView grid spacing updates for first row and column by
@KarthikRajaKalaimani in #34527
  <details>
  <summary>🔧 Fixes</summary>

- [[MAUI] I2_Vertical grid for horizontal Item Spacing and Vertical Item
Spacing - horizontally updating the spacing only applies to the second
column](#34257)
  </details>

- CarouselView: Fix cascading PositionChanged/CurrentItemChanged events
on collection update by @praveenkumarkarunanithi in
#31275
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] CurrentItemChangedEventArgs and PositionChangedEventArgs
Not Working Properly in
CarouselView](#29529)
  </details>

- [Windows] Fixed ItemSpacing doesn't work in Carousel View by
@SubhikshaSf4851 in #30014
  <details>
  <summary>🔧 Fixes</summary>

- [ItemSpacing on CarouselView is not applied on
Windows.](#29772)
  </details>

- Fix CollectionView not scrolling to top on iOS status bar tap by
@jfversluis in #34687
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] UICollectionView ScrollToTop does not
work](#19866)
  </details>

- [iOS] Fixed CollectionView Scroll Jitter for TextType HTML Labels by
@SubhikshaSf4851 in #34383
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView scrolling is jittery when ItemTemplate contains Label
with TextType="Html" in .NET
10](#33065)
  </details>

- Fix CollectionView Header is not visible when ItemsSource is not set
and an EmptyView is set in iOS, Mac platform by @KarthikRajaKalaimani in
#34989
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView Header is not visible when ItemsSource is not set and
EmptyView is set in iOS, Mac
platform](#34897)
  </details>

- [Android] Fix CollectionView EmptyView not displayed correctly by
@KarthikRajaKalaimani in #34956
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] CollectionView - EmptyView not displayed
correctly](#34861)
  </details>

- [iOS] Fix CollectionView ScrollOffset not resetting when ItemsSource
changes by @SyedAbdulAzeemSF4852 in
#34488
  <details>
  <summary>🔧 Fixes</summary>

- [[IOS] CollectionView ScrollOffset does not reset when the ItemSource
is changed in iOS.](#26366)
- [Re-enable Issue7993 test on iOS/Catalyst - CollectionView scroll
position not reset when updating
ItemsSource](#33500)
  </details>

- [Revert] [iOS] Fixed CollectionView Scroll Jitter for TextType HTML
Labels by @SubhikshaSf4851 in #35341

## Core Lifecycle
- [Android] Fix NRE in ContainerView when Android Context is null during
lifecycle transition by @rmarinho in
#34901
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] NullReferenceException in NavigationRootManager.Connect
when mapping Window
content](#34900)
  </details>

## DateTimePicker
- [Android] Fix for TimePicker Dialog doesn't update the layout when
rotating the device with dialog open by @HarishwaranVijayakumar in
#31910
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] TimePicker Dialog doesn't update the layout when rotating
the device with dialog
open](#31658)
  </details>

- [Android, iOS] Fixed TimePicker FlowDirection Not Applied Across
Platforms by @Dhivya-SF4094 in #30369
  <details>
  <summary>🔧 Fixes</summary>

- [TimePicker FlowDirection Not Working on All
Platforms](#30192)
  </details>

- [Windows] Fixed TimePicker CharacterSpacing issue by @SubhikshaSf4851
in #30533
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] TimePicker CharacterSpacing Property Not Working on
Windows](#30199)
  </details>

- [MacCatalyst] Fix DatePicker Opened/Closed events not being raised by
@SubhikshaSf4851 in #34970
  <details>
  <summary>🔧 Fixes</summary>

- [[MacCatalyst] DatePicker Opened and Closed events are not raised on
Mac platform](#34848)
  </details>

## Dialogalert
- [Android] Fix AlertDialog, ActionSheet, and Prompt render with
Material 2 styles when Material 3 is enabled by @HarishwaranVijayakumar
in #35121
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] AlertDialog, ActionSheet, and Prompt render with Material 2
styles when Material 3 is
enabled](#35119)
  </details>

## Docs
- docs: Add UITesting-Guide, ReleasePlanning, and ReleaseProcess to
docs/README.md index by @PureWeen in
#35195

- docs: Fix hardcoded path and add library overview in Essentials.AI
README by @PureWeen in #35194

- docs: Update branch reference from net10.0 to net11.0 in
DEVELOPMENT.md by @PureWeen in #35193

## Drawing
- Fix Path Rendering Issue Inside StackLayout When Margin Is Set by
@Shalini-Ashokan in #28071
  <details>
  <summary>🔧 Fixes</summary>

- [Path does not render if it has
Margin](#13801)
  </details>

- Fixed FlowDirection property not working on Drawable control and
GraphicsView by @Dhivya-SF4094 in
#34557
  <details>
  <summary>🔧 Fixes</summary>

- [[Android, Windows, iOS, macOS] FlowDirection property not working on
BoxView Control](#34402)
  </details>

- [iOS & Mac] Fix image tile misalignment in GraphicsView ImagePaint by
@SubhikshaSf4851 in #34935
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Image resized with ResizeMode.Fit is not rendered correctly in
GraphicsView](#34755)
  </details>

- Fix Shadow does not honour Styles by @KarthikRajaKalaimani in
#35081
  <details>
  <summary>🔧 Fixes</summary>

- [Shadow does not honour
Styles](#19560)
  </details>

## Entry
- [iOS/macCatalyst] Fix Entry and Editor BackgroundColor reset when set
to null by @Shalini-Ashokan in #34741
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Maccatalyst] Entry & Editor BackgroundColor not reset to
Null](#34611)
  </details>

- [Windows] Fix password Entry crash when setting text on empty field by
@praveenkumarkarunanithi in #33891
  <details>
  <summary>🔧 Fixes</summary>

- [[WinUI] Password Obfuscation causes unhandled
crash](#33334)
  </details>

## Essentials
- [Essentials] Use mean sea level altitude on Android API 34+ by
@KitKeen in #35097
  <details>
  <summary>🔧 Fixes</summary>

- [Add support for MslAltitudeMeters in Essentials Geolocation on
Android](#27554)
  </details>

## Flyout
- Fixed Flyout Not Displayed on Android When FlyoutWidth Is Set Only for
Desktop via OnIdiom by @NanthiniMahalingam in
#29028
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] FlyoutWidth with OnIdiom shows no
flyout](#13243)
  </details>

- Revert "[Windows] Fix Flyout/Locked mode header collapse regression
causing UI test failures on candidate branch" by @kubaflo in
#35339

- Revert "Revert "[Windows] Fix Flyout/Locked mode header collapse
regression causing UI test failures on candidate branch"" by @kubaflo in
#35342

## Flyoutpage
- Fix [Android] Title of FlyOutPage is not updating anymore after
showing a NonFlyOutPage by @KarthikRajaKalaimani in
#34839
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Title of FlyOutPage is not updating anymore after showing a
NonFlyOutPage](#33615)
  </details>

## Label
- [iOS] Fix span Tap gesture on wrapped Label lines in iOS 26+ by
@SubhikshaSf4851 in #34640
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS]Span TapGestureRecognizer does not work on the second line of
the span, if the span is wrapped to the next
line](#34504)
  </details>

## Layout
- Fixed Stacklayout is not rendered when clip is applied and StackLayout
placed child to the Border control in iOS/ Mac platform by
@KarthikRajaKalaimani in #33330
  <details>
  <summary>🔧 Fixes</summary>

- [[Mac/iOS] StackLayout fails to render content while applying Clip,
and the layout is placed inside a Border with Background in .NET
MAUI](#33241)
  </details>

## Map
- Fix Changing Location on a Pin does nothing by @NirmalKumarYuvaraj in
#30201
  <details>
  <summary>🔧 Fixes</summary>

- [[Maps] [Regression from Xamarin.Forms.Maps] Changing Location on a
Pin does nothing](#12916)
  </details>

## Mediapicker
- [iOS] Fix HEIC images picked via PickPhotosAsync not displayed by
@HarishwaranVijayakumar in #34954
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] [Regression] HEIC images picked via PickPhotosAsync not
displayed](#34953)
  </details>

- [Android] Fix MediaPicker.PickPhotosAsync UnauthorizedAccessException
on API 28 and below by @HarishwaranVijayakumar in
#34981
  <details>
  <summary>🔧 Fixes</summary>

- [MediaPicker.PickPhotos fails to modify image, tries to load original
source, fails to load source on Android
9.0](#34889)
  </details>

## Pages
- [iOS] Fix ContentPage with ToolbarItem Clicked event leaks when
presented as modal page by @devanathan-vaithiyanathan in
#35009
  <details>
  <summary>🔧 Fixes</summary>

- [ContentPage with ToolbarItem Clicked event leaks when presented as
modal page](#34892)
  </details>

## Platform
- [Android] Fix OnBackButtonPressed not invoked for Shell by
@Dhivya-SF4094 in #35150
  <details>
  <summary>🔧 Fixes</summary>

- [On Screen Back Button Does Not Fire OnBackButtonPressed in
Android](#9095)
  </details>

## RadioButton
- Fix RadioButtonGroup not working with ContentView by @Dhivya-SF4094 in
#34781
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButtonGroup not working with
ContentView](#34759)
  </details>

- [Windows] Fix for RadioButton BorderColor and BorderWidth not updated
at runtime by @SyedAbdulAzeemSF4852 in
#28335
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButton Border color not working for focused visual
state](#15806)
  </details>

- [iOS] Fix RadioButton BackgroundColor bleeding outside CornerRadius by
@SyedAbdulAzeemSF4852 in #34844
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] RadioButton BackgroundColor bleeds outside
CornerRadius](#34842)
  </details>

## SafeArea
- [iOS] Fix stale bottom safe area after changing SafeAreaEdges with
keyboard open by @praveenkumarkarunanithi in
#35083
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] ContentPage bottom has white space after changing SafeAreaEdges
while keyboard is open](#34846)
  </details>

## ScrollView
- [Windows] Fix Preserve ScrollView offsets when Orientation changes to
Neither by @SubhikshaSf4851 in #34827
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] ScrollView offsets do not preserve when Orientation changes
to Neither](#34671)
  </details>

## Searchbar
- [iOS] Fix SearchBar unexpected left margin in iPad windowed mode on 26
Version by @SubhikshaSf4851 in #34704
  <details>
  <summary>🔧 Fixes</summary>

- [in iPad windowed mode SearchBar adds left margin equivaltent to
SafeAreaInsets when placed inside
grid](#34551)
  </details>

## Shell
- [Windows] Fix for Shell.FlyoutBehavior="Flyout" forces the title
height space above the tab bar even if the page title is empty by
@BagavathiPerumal in #30382
  <details>
  <summary>🔧 Fixes</summary>

- [(Windows) Shell.FlyoutBehavior="Flyout" forces the title height space
above the tab bar even if the page title is
empty](#30254)
  </details>

- Fix Shell flyout items scrolling behind FlyoutHeader on iOS by @Qythyx
in #34936
  <details>
  <summary>🔧 Fixes</summary>

- [Shell flyout items scroll behind FlyoutHeader on
iOS](#34925)
  </details>

- [iOS, Mac] Fix Shell.CurrentState.Location stale in OnNavigated after
GoToAsync by @Vignesh-SF3580 in
#34880
  <details>
  <summary>🔧 Fixes</summary>

- [Shell.OnNavigated not called for route
navigation](#34662)
  </details>

- [iOS26]Fix
BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate UITest
fails by @devanathan-vaithiyanathan in
#34890
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS 26] BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate
test fails with
TimeoutException](#34771)
  </details>

- [iOS] Fix Shell page memory leak when using TitleView with x:Name by
@Shalini-Ashokan in #35082
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Title view memory
leak](#34975)
  </details>

- [Material 3] Fix Material 2 color flash in AppBar when switching tabs
for the first time by @Dhivya-SF4094 in
#35117
  <details>
  <summary>🔧 Fixes</summary>

- [Material 3: AppBar briefly displays Material 2 colors when switching
tabs for the first time](#35116)
  </details>

- [Android] Fix Shell/TabbedPage "More" BottomSheet uses hard-coded M2
colors when Material3 is enabled by @HarishwaranVijayakumar in
#35129
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Shell/TabbedPage "More" BottomSheet uses hard-coded M2
colors when Material3 is
enabled](#35127)
  </details>

- [Android] Shell: Fix top-tab unselected text visibility in Material 3
light theme by @SyedAbdulAzeemSF4852 in
#35128
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Shell top-tab unselected text appears too faint in Material
3 light theme](#35125)
  </details>

- Fix Shell.Items.Clear() memory leak by disconnecting child handlers on
removal (#34898) by @Shalini-Ashokan in
#35031
  <details>
  <summary>🔧 Fixes</summary>

- [Shell.Items.Clear() does not disconnect handlers
correctly](#34898)
  </details>

- [iOS&Mac] Fix Shell SearchHandler Query update on Initial load by
@SubhikshaSf4851 in #35008
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS&Mac] Shell SearchHandler Query not shown in search bar on
initial load](#35005)
  </details>

## SwipeView
- [iOS,MacCatalyst] Fix for SwipeView.Open() throwing an
ArgumentException on the second programmatic call by @BagavathiPerumal
in #34982
  <details>
  <summary>🔧 Fixes</summary>

- [[net 11.0][iOS,MacCatalyst] SwipeView.Open() throws ArgumentException
on second programmatic
call](#34917)
  </details>

- [Android/iOS] Fix SwipeItem visibility change causing double command
execution in Execute mode by @praveenkumarkarunanithi in
#35087
  <details>
  <summary>🔧 Fixes</summary>

- [Changing visibility on an SwipeItem causes multiple items to be
executed](#7580)
  </details>

## Switch
- [iOS] Fix Switch ThumbColor reset on iOS 26+ theme changes. by
@Shalini-Ashokan in #33953
  <details>
  <summary>🔧 Fixes</summary>

- [Switch ThumbColor not Initialized Using VisualStateManager on iOS
Device](#33783)
- [I9-On macOS 26.2, the "Animate scroll" button is white by default on
iOS and Maccatalyst
platforms.](#33767)
  </details>

## TabbedPage
- [Windows] TabbedPage: Refresh layout when NavigationView size changes
by @BagavathiPerumal in #26217
  <details>
  <summary>🔧 Fixes</summary>

- [TabbedPage - ScrollView not allowing scrolling when it
should](#26103)
- [TabbedPage App on resize hides page bottom
content](#11402)
- [Grid overflows child ContentPage of parent TabbedPage on initial load
and when resizing on
Windows](#20028)
  </details>

- [Android] Material 3 Fixed BottomNavigationView overflowing in Tabbed
page by @NirmalKumarYuvaraj in #35064
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Material3 - TabbedPage bottom tabs overflowing the
contents](#35063)
  </details>

- [Windows] Fix for Multiple Tabs Being Selected in WinUI TabbedPage by
@SyedAbdulAzeemSF4852 in #33312
  <details>
  <summary>🔧 Fixes</summary>

- [WinUI TabbedPage can have multiple tabs
selected](#31799)
  </details>

## Theming
- [iOS] Fix StaticResource Hot Reload crash on iOS by @StephaneDelcroix
in #35020
  <details>
  <summary>🔧 Fixes</summary>

- [The maui app quit and no errors in error list after editing
ResourceDictionary XAML file on iOS Simulator with MAUI SR6
10.0.60](#35018)
  </details>

## Toolbar
- [Windows] Fix for CS1061 build error caused by missing
HasMenuBarContent property in MauiToolbar by @BagavathiPerumal in
#35040

## Tooling
- Fix VisualStateGroups duplicate name crash with implicit styles
(#34716) by @StephaneDelcroix in
#34719
  <details>
  <summary>🔧 Fixes</summary>

- [SourceGen: VisualStateManager.VisualStateGroups causes 'Names must be
unique' at startup](#34716)
  </details>

## WebView
- Refactor the HybridWebView and properly support complex parameters by
@mattleibow in #32491

- [Android] Fix WebView scrolling inside ScrollView by @Shalini-Ashokan
in #33133
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] WebView's content does not scroll when placed inside a
ScrollView](#32971)
  </details>


<details>
<summary>🔧 Infrastructure (1)</summary>

- [Windows] Fix Narrator announcing ContentView children twice when
Description is set by @praveenkumarkarunanithi in
#33979
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] SemanticProperties.Description announced twice when set on
focusable container cell (Label
inside)](#33373)
  </details>

</details>

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

- [Testing] SafeArea Feature Matrix Test Cases for ContentPage by
@TamilarasanSF4853 in #34877
- [Windows] Fix CollectionView ScrollTo related test cases failed in CI
by @HarishwaranVijayakumar in #34907
  <details>
  <summary>🔧 Fixes</summary>

- [[Testing][Windows]CollectionView ScrollTo related test cases failed
in CI](#34772)
  </details>
- [Testing] Fixed Build error on inflight/ candidate PR 35234 by
@HarishKumarSF4517 in #35241
- Fix CI for
ValidateKeyboardRuntime_SwitchContainerToSoftInput_WhileKeyboardOpen
test failure in May 4th Candidate by @devanathan-vaithiyanathan in
#35307
- [Windows] Fix Flyout/Locked mode header collapse regression causing UI
test failures on candidate branch by @BagavathiPerumal in
#35312
- [iOS/macCatalyst] [Candidate Fix] Editor shadow and theme regression
caused by BackgroundColor reset on initial handler connection by
@Shalini-Ashokan in #35343
- [Testing] Fixed UI test image failure in PR 35234 - [30/03/2026]
Candidate - 1 by @HarishKumarSF4517 in
#35325
- [iOS] Fix ShellFeatureMatrix test failures on candidate branch by
@Vignesh-SF3580 in #35346
- [Windows] Fix Issue29529VerifyPreviousPositionOnInsert test failure on
candidate branch by @praveenkumarkarunanithi in
#35398
- [Android] [Candidate Fix] Shell: Fix handler disconnect timing to
preserve WebView navigation and memory leak fix by @Shalini-Ashokan in
#35417
- [Testing]Revert 'Fix Preserve ScrollView offsets when Orientation
changes to Neither' by @TamilarasanSF4853 in
#35412
- [Windows] Fix VerifyAllIndicatorDotsShowShadowsWhenIndicatorSize test
failure on candidate branch by @praveenkumarkarunanithi in
#35458
- [Testing] Fixed test failure in PR 35234 - [05/08/2026] Candidate by
@TamilarasanSF4853 in #35362
- [Testing] Fixed test failure in PR 35234 - [05/04/2026] Candidate - 3
by @TamilarasanSF4853 in #35639

</details>

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

- [UIKit] Avoid useless measure invalidation propagation cycles by
@albyrock87 in #33459
- BindableObject property access micro-optimizations by @albyrock87 in
#33584
- Extract filename from DisplayName and add extension if missing by
@mattleibow in #35050
- [core] Add keyed-DI screenshot extensibility for 3rd-party platform
backends by @Redth in #35096
  <details>
  <summary>🔧 Fixes</summary>

- [`ViewExtensions.CaptureAsync(IView)` and `IPlatformScreenshot` need
extensibility for third-party platform
backends](#34266)
  </details>
- Fix MainThread throwing on custom platform backends by @Redth in
#35070
  <details>
  <summary>🔧 Fixes</summary>

- [`MainThread.BeginInvokeOnMainThread` throws on custom platform
backends - Common UI-thread marshaling pattern crashes; `Dispatcher`
works but isn't the documented/recommended
path](#34101)
  </details>
- Tests: Add 11 missing UnitConverters unit tests by @PureWeen in
#35191

</details>

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

Fixes #7580, Fixes #9095, Fixes #11402, Fixes #12916, Fixes #13243,
Fixes #13801, Fixes #15806, Fixes #19560, Fixes #19690, Fixes #19866,
Fixes #20028, Fixes #26103, Fixes #26366, Fixes #27554, Fixes #29529,
Fixes #29772, Fixes #30192, Fixes #30199, Fixes #30254, Fixes #31658,
Fixes #31799, Fixes #32971, Fixes #33065, Fixes #33241, Fixes #33334,
Fixes #33373, Fixes #33500, Fixes #33615, Fixes #33767, Fixes #33783,
Fixes #34101, Fixes #34257, Fixes #34266, Fixes #34402, Fixes #34504,
Fixes #34551, Fixes #34611, Fixes #34662, Fixes #34671, Fixes #34716,
Fixes #34755, Fixes #34759, Fixes #34771, Fixes #34772, Fixes #34842,
Fixes #34846, Fixes #34848, Fixes #34861, Fixes #34889, Fixes #34892,
Fixes #34897, Fixes #34898, Fixes #34900, Fixes #34917, Fixes #34925,
Fixes #34953, Fixes #34975, Fixes #35005, Fixes #35018, Fixes #35063,
Fixes #35116, Fixes #35119, Fixes #35125, Fixes #35127

</details>

**Full Changelog**:
main...inflight/candidate
@PureWeen PureWeen modified the milestones: .NET 10 SR7, .NET 10 SR8 Jun 11, 2026
Shalini-Ashokan pushed a commit to Shalini-Ashokan/maui that referenced this pull request Jun 15, 2026
…yboard open (dotnet#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes dotnet#34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
Shalini-Ashokan pushed a commit to Shalini-Ashokan/maui that referenced this pull request Jun 15, 2026
…yboardOpen test failure in May 4th Candidate (dotnet#35307)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details
PR dotnet#35083 fixed the stale safe area issue when switching from All to
Container while the keyboard was open.
But that change introduced a regression for the opposite runtime flow.
 
On iOS, when switching from Container to SoftInput while the keyboard is
already open, MauiView may not receive a new keyboard show event.
Because the keyboard state was cleared during unsubscribe, the view can
miss the current keyboard state and fail to apply the expected
keyboard-related bottom inset.

### Description of Change

<!-- Enter description of the fix in this section -->
This change updates iOS keyboard handling in MauiView.cs:312. When
switching to SoftInput while the keyboard is already open, it restores
keyboard state immediately and refreshes layout, so safe area updates
correctly.

### Issues Fixed
* ValidateKeyboardRuntime_SwitchContainerToSoftInput_WhileKeyboardOpen
Dhivya-SF4094 pushed a commit to Dhivya-SF4094/maui that referenced this pull request Jun 15, 2026
…yboard open (dotnet#35083)

<!-- Please let the below note in for people that find this PR -->
   > [!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!
 
### Root Cause
When `SafeAreaEdges` changes from a mode that includes `SoftInput`
(e.g., `All`) to one that does not (e.g., `Container`), the view
unsubscribes from iOS keyboard notifications. However, the keyboard
state (`_isKeyboardShowing`, `_keyboardFrame`) was not cleared. If the
keyboard was open during unsubscription and later dismissed, the
`OnKeyboardWillHide` event is never received. When switching back to a
`SoftInput` mode, the view re-subscribes with stale state, applying
incorrect bottom padding equal to the old keyboard height instead of the
home indicator inset.
 
### Description of Change
Added state cleanup in `UnsubscribeFromKeyboardNotifications` in
`MauiView.cs`. When unsubscribing, if the keyboard was previously
visible, the method now clears the keyboard state, invalidates the safe
area, and triggers a layout update. This prevents stale keyboard state
from persisting across subscribe/unsubscribe cycles while preserving
existing behavior in all other scenarios.

Also added a test in `Issue28986_ContentPage` that reproduces the exact
sequence: switch to All, open keyboard, change to Container, dismiss
keyboard, switch back to All, and verify the layout returns to baseline
without phantom padding.
 
### Issues Fixed
Fixes dotnet#34846     
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/48e5afe8-4b6c-4c5a-b223-91312bf212e3"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a7fa1af6-8927-4fed-a7f2-f8011bdbef8f"
/> |
Dhivya-SF4094 pushed a commit to Dhivya-SF4094/maui that referenced this pull request Jun 15, 2026
…yboardOpen test failure in May 4th Candidate (dotnet#35307)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details
PR dotnet#35083 fixed the stale safe area issue when switching from All to
Container while the keyboard was open.
But that change introduced a regression for the opposite runtime flow.
 
On iOS, when switching from Container to SoftInput while the keyboard is
already open, MauiView may not receive a new keyboard show event.
Because the keyboard state was cleared during unsubscribe, the view can
miss the current keyboard state and fail to apply the expected
keyboard-related bottom inset.

### Description of Change

<!-- Enter description of the fix in this section -->
This change updates iOS keyboard handling in MauiView.cs:312. When
switching to SoftInput while the keyboard is already open, it restores
keyboard state immediately and refreshes layout, so safe area updates
correctly.

### Issues Fixed
* ValidateKeyboardRuntime_SwitchContainerToSoftInput_WhileKeyboardOpen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-safearea Issues/PRs that have to do with the SafeArea functionality 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-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS] ContentPage bottom has white space after changing SafeAreaEdges while keyboard is open

6 participants