[iOS] Fix infinite layout cycle when both parent and child views respond to SafeArea#32797
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes an infinite layout update cycle on iOS that occurs when using TranslateToAsync with SafeArea adjustments. The issue was caused by both parent and child views in a nested Grid hierarchy applying SafeArea logic concurrently, leading to continuous layout recalculations when views are translated in and out of the SafeArea region.
Key Changes
- Introduced
IsParentHandlingSafeArea()method to check if a parent view is already applying safe area adjustments - Modified safe area application logic to skip adjustments when a parent is already handling them
- Added UI test to verify the fix works correctly
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Core/src/Platform/iOS/MauiView.cs | Adds parent safe area check to prevent duplicate SafeArea adjustments in nested views |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32586.cs | NUnit test that verifies layout responsiveness with TranslateToAsync and SafeArea |
| src/Controls/tests/TestCases.HostApp/Issues/Issue32586.cs | Test page reproducing the infinite layout cycle scenario with nested grids and animations |
jfversluis
left a comment
There was a problem hiding this comment.
Please address the comment: https://github.com/dotnet/maui/pull/32797/files#r2560134946
We don't want this to cause a performance hit
@jfversluis , yes, I have already tested different cache based approaches on my side. Unfortunately, none of them worked in all edge cases. For example, when the parent’s SafeAreaEdges is reset to None at runtime, the behavior is still not as expected. In that scenario, we would need to check the other child views in the hierarchy as well. I will check if I can find a reliable solution for this scenario. |
|
Converting to draft while its still being worked on |
|
Hi @@Tamilarasan-Paranthaman. |
|
/rebase |
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Added test cases and improved the fix ·
|
| Reviewer | Feedback | Status |
|---|---|---|
| copilot-pull-request-reviewer | Wrong comment "Create TestButton" should be "Create TestLabel" | Resolved |
| copilot-pull-request-reviewer | Comment says "deadlock" but should say "infinite layout update cycle" | Resolved |
| copilot-pull-request-reviewer | IsParentHandlingSafeArea() nitpick: consider caching | Addressed in latest commit |
| jfversluis | CHANGES_REQUESTED: Performance concern about hierarchy walk | Addressed - caching added in latest commit |
Notable: jfversluis's CHANGES_REQUESTED was about performance (no caching). The latest commit (ed28c5e) addresses this by adding _parentHandlesSafeArea nullable bool field with proper cache invalidation in MovedToWindow() and SafeAreaInsetsDidChange().
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #32797 | Skip SafeArea in child if parent already handles SafeArea - IsParentHandlingSafeArea() with caching | PASS (Gate) | MauiView.cs (+29/-1) | Original PR - includes caching |
🚦 Gate — Test Verification
📝 Review Session — Added test cases and improved the fix · ed28c5e
Result PASSED:
Platform: ios (iPhone 11 Pro Simulator, iossimulator-arm64)
Mode: Full Verification
Test Filter: Issue32586
- Tests FAIL without fix
- Tests PASS with fix
Fix files verified:
src/Core/src/Platform/iOS/MauiView.cs
🔧 Fix — Analysis & Comparison
📝 Review Session — Added test cases and improved the fix · ed28c5e
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #32797 | Skip SafeArea in child if parent already handles SafeArea - IsParentHandlingSafeArea() with _parentHandlesSafeArea caching | PASS (Gate) | MauiView.cs (+29/-1) | Original PR fix |
| 1 | try-fix (prior session) | Layout epoch coordination | BLOCKED | MauiView.cs | Simulator version mismatch |
| 2 | try-fix (prior session) | Thread-static layout depth counter | FAIL | MauiView.cs | UIKit doesn't run child LayoutSubviews synchronously within parent |
| 3 | try-fix (prior session) | SafeArea owner propagation (downward) | BLOCKED | MauiView.cs | Simulator version |
| 4 | try-fix (prior session) | Debounce SafeArea updates with per-view generation counter | PASS | MauiView.cs (+20/-3) | Generation counter incremented in SafeAreaInsetsDidChange(). Simpler than PR (+20/-3 vs +29/-1), more robust to runtime changes |
| 5 | try-fix (prior session) | Guard InvalidateAncestorsMeasures with _hasInvalidatedAncestorsForSafeArea boolean; reset on genuine value changes | FAIL | MauiView.cs | UIKit's SafeAreaInsets genuinely change each cycle; value-based dedup cannot break this cycle |
| 6 | try-fix (prior session) | Parent safe-area delta (subtract parent computed _safeArea from child) | FAIL | MauiView.cs | Issue32586 still fails; delta padding does not stop parent/child invalidation loop |
| 7 | try-fix (prior session) | Inset-equality guard (skip adjustments when parent/child SafeAreaInsets match) | FAIL | MauiView.cs | VerifyRuntimeSafeAreaEdgesChange fails; SafeAreaEdges=None doesn't move content because UIKit insets remain equal |
| 8 | try-fix (prior session) | Safe area ancestor invalidation guard - boolean gates entire safe-area-changed block in LayoutSubviews | FAIL | MauiView.cs | Multiple entry points (InvalidateMeasure also sets _safeAreaInvalidated=true); single boolean cannot break it |
Note: Current session try-fix attempts blocked by API rate limiting. Results imported from prior complete agent session (commit ed28c5e).
Root Cause Analysis
In .NET 10 (PR #30629), SafeArea handling was refactored so each MauiView independently determines whether to apply SafeArea adjustments in ValidateSafeArea(). When nested views (e.g., parent Grid + child Grid) both have SafeArea=Container (the default), each view's SafeArea-triggered layout change calls InvalidateAncestorsMeasures(), which causes the other view to re-layout. Since UIKit recalculates SafeAreaInsets on each layout pass (values genuinely change as frames adjust), value-based deduplication cannot break the cycle.
Key Technical Insight: UIKit's LayoutSubviews() is asynchronous - child layout runs AFTER parent completes. Any temporal/execution-scoped approach (flags, try-finally, depth counters) fails because there's no temporal overlap between parent and child layout passes. Only approaches with persistent state (cached bools, generation counters) work.
Exhausted: Yes (imported from prior complete session; all viable approaches were tested)
Selected Fix: PR's fix - The hierarchy walk + parent check approach directly addresses the root cause by having child views defer SafeArea handling to their parent when the parent already handles it. While the generation counter (candidate #4) is simpler, the PR's approach is semantically clearer (explicitly encodes the "parent handles SafeArea" relationship) and addresses the root cause rather than just debouncing the symptom.
📋 Report — Final Recommendation
📝 Review Session — Added test cases and improved the fix · ed28c5e
Final Recommendation: APPROVE
Summary
PR #32797 fixes an iOS infinite layout cycle regression introduced in .NET 10 (PR #30629). When nested views both have SafeArea=Container (the default), each view's SafeArea-triggered layout update calls InvalidateAncestorsMeasures(), causing the sibling/parent to re-layout, creating an infinite cycle that deadlocks the UI.
Title Assessment
Current: [iOS] Fix infinite layout cycle when both parent and child views respond to SafeArea
Verdict Accurate platform prefix, describes the behavior fix clearly, searchable.Good :
Description Assessment
Verdict Has NOTE block, root cause, description of change, issues fixed, screenshots.Good :
Minor suggestion: The description could be enhanced with:
- A "What NOT to Do" note about temporal/execution-scoped approaches (flags, depth counters) failing because UIKit's LayoutSubviews is asynchronous
- Noting the cache invalidation strategy for runtime SafeAreaEdges changes
Root Cause
In .NET 10 (PR #30629), each MauiView independently determines whether to apply SafeArea adjustments in ValidateSafeArea(). When nested views (e.g., parent Grid + child Grid) both have SafeArea=Container (the default), each view's SafeArea-triggered layout change calls InvalidateAncestorsMeasures(), causing the other view to re-layout. Since UIKit recalculates SafeAreaInsets on each layout pass (values genuinely change as frames adjust), value-based deduplication cannot break the cycle. This creates an infinite layout loop that deadlocks the UI.
Key insight: UIKit's LayoutSubviews() is child layout runs AFTER parent completes. Any temporal/execution-scoped approach (flags, try-finally, depth counters) fails because there's no temporal overlap between parent and child layout passes. Only approaches with persistent state (cached bools, generation counters) work.asynchronous
Fix Analysis
The PR adds IsParentHandlingSafeArea() in MauiView.cs which:
- Walks up the iOS view hierarchy to find a parent
MauiViewwith_appliesSafeAreaAdjustments=trueand implementingISafeAreaView/ISafeAreaView2 - If such a parent exists, the child skips SafeArea adjustments, breaking the infinite cycle
- Caches the result in
_parentHandlesSafeArea(nullable bool) - Invalidates cache in
SafeAreaInsetsDidChange()andMovedToWindow()for runtime correctness
The fix directly addresses the root cause by having child views defer SafeArea handling to their parent. The caching addresses jfversluis's performance concern (hierarchy walk only on first check per layout context).
Code Review Findings
Looks Good
_parentHandlesSafeAreacache uses nullable bool pattern (same as existing_scrollViewDescendant) - consistent with codebase- Cache invalidation on
SafeAreaInsetsDidChange()andMovedToWindow()are correct trigger points - XML documentation on
IsParentHandlingSafeArea()is clear and helpful - Test covers both the animation scenario (Issue32586) and navigation crash scenario (Issue33595)
VerifyRuntimeSafeAreaEdgesChangetest validates the runtime SafeAreaEdges toggle behavior
- Comment accuracy in Issue32586.cs line 182: Still says
// This causes deadlock on iOS .NET copilot reviewer flagged this as misleading (it's an infinite layout cycle, not a deadlock). This thread shows as Resolved but the comment wasn't updated in the code.10#### - Issue33595.cs indentation: Uses 4-space indentation while rest of repo uses tabs. Minor but inconsistent.
- Issue32586.cs
#if IOS || ANDROID: The test is Android-tagged but the fix is iOS-only. Android will run the test but won't reproduce the bug (confirming no regression on Android). This is acceptable but the[Issue]attribute specifiesPlatformAffected.iOS.
Gate Result
Tests FAIL without fix, PASS with fix (iOS, iPhone 11 Pro Simulator)PASSED
Alternative Fix Considered
An independent generation-counter approach (try-fix #4 from prior session) also passes all tests with a simpler diff (+20/-3 vs +29/-1). However, the PR's approach is semantically clearer and has been reviewed by the team. The generation counter is a viable alternative if the hierarchy walk proves problematic in practice.
📋 Expand PR Finalization Review
Title: ✅ Good
Current: [iOS] Fix infinite layout cycle when both parent and child views respond to SafeArea
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!
Root Cause
On iOS, when both a parent and child MauiView implement ISafeAreaView or ISafeAreaView2 with SafeAreaEdges.Container (the default), both views independently call ValidateSafeArea() and both set _appliesSafeAreaAdjustments = true. This leads to both views applying padding adjustments to move content out of the safe area. When one of those views is involved in an animation (e.g., TranslateToAsync), the competing safe area recalculations create a feedback loop — each layout pass triggered by the animation causes both views to re-evaluate and re-apply safe area, which triggers another layout pass, causing an infinite cycle that deadlocks the UI.
This affected at least two scenarios:
- Layout issue using TranslateToAsync causes infinite property changed cycle on iOS #32586 – A Grid containing a VerticalStackLayout, with a footer view animated via
TranslateToAsync, froze the UI indefinitely. - [net10] iOS 18.6 crashing on navigating to a ContentPage with Padding set and Content set to a <Grid RowDefinitions="*,Auto"> with ScrollView on row 0 #33595 – A
ContentPagewithPaddingset containing aGridwithRowDefinitions="*,Auto"and aScrollViewin row 0 caused the app to freeze/crash on iOS 18.6 with .NET 10.
Both issues are regressions in .NET 10 (worked in .NET 9 / 9.0.120 SR12 and earlier).
Description of Change
src/Core/src/Platform/iOS/MauiView.cs
- Added new
bool? _parentHandlesSafeAreacached field (nullable, following the same pattern as_scrollViewDescendant). - Added new
IsParentHandlingSafeArea()method that walks the view hierarchy upward to find any ancestorMauiViewthat already has_appliesSafeAreaAdjustments = trueand implementsISafeAreaVieworISafeAreaView2. - Modified
ValidateSafeArea()so that_appliesSafeAreaAdjustmentsis only set totruewhen no parent is already applying safe area adjustments:_appliesSafeAreaAdjustments = !parentHandlingSafeArea && RespondsToSafeArea() && !_safeArea.IsEmpty - Cache (
_parentHandlesSafeArea) is invalidated in:SafeAreaInsetsDidChange()— when the device safe area insets change (e.g., rotation, keyboard)MovedToWindow()— when the view is added to or removed from the view hierarchy
Tests (src/Controls/tests/)
- Added
TestCases.HostApp/Issues/Issue32586.cs— reproduces the TranslateToAsync infinite cycle; includes toggle buttons for parent/child SafeAreaEdges to test runtime behavior. - Added
TestCases.HostApp/Issues/Issue33595.cs— reproduces the navigation freeze with Grid+ScrollView+Padding. - Added
TestCases.Shared.Tests/Tests/Issues/Issue32586.cs— two UI tests: animation works correctly, SafeAreaEdges toggling at runtime works without loop. - Added
TestCases.Shared.Tests/Tests/Issues/Issue33595.cs— navigation to the affected page succeeds without freeze.
Key Technical Details
Types involved:
MauiView— the base iOS platform view insrc/Core/src/Platform/iOS/ISafeAreaView— legacy safe area interface (IgnoreSafeAreaproperty)ISafeAreaView2— newer safe area interface withSafeAreaEdges/GetSafeAreaRegionsForEdge()_appliesSafeAreaAdjustments— internalboolflag indicating this view is actively applying safe area padding
Key invariant: In a view hierarchy, at most one ancestor MauiView applies safe area adjustments. The topmost view that implements ISafeAreaView/ISafeAreaView2 and responds to safe area takes ownership; descendants skip their adjustments.
Caching strategy: _parentHandlesSafeArea is a bool? nullable field initialized to null (not yet computed). It is populated on first call to IsParentHandlingSafeArea() and cleared when the hierarchy or safe area changes. This follows the same pattern as _scrollViewDescendant.
Issues Fixed
Platforms Tested
- iOS
- Android (fix is iOS-specific; platform layer code is iOS-only)
- Windows
- Mac Catalyst
Code Review: ⚠️ Issues Found
Code Review — PR #32797
🔴 Critical Issues
None.
🟡 Suggestions
1. Wrong Platform Guard in Issue32586.cs UI Test
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32586.cs
Line: 1
#if IOS || ANDROIDProblem: The || ANDROID is incorrect. The bug (#32586) is iOS-only — it is a regression in MauiView.cs on iOS's platform layer. The SafeAreaEdges concept and MauiView's ValidateSafeArea() only apply to iOS. Running this test on Android would test behavior that doesn't exist there, and the assertions (e.g., verifying TopMarker.Y > 0 due to safe area inset) would produce meaningless or incorrect results on Android.
Additionally, the related fix in Issue33595.cs is correctly guarded with #if IOS only.
Recommendation: Change to:
#if IOS2. Misleading Comment in Issue32586.cs HostApp
File: src/Controls/tests/TestCases.HostApp/Issues/Issue32586.cs
Line: ~182
// This causes deadlock on iOS .NET 10
await FooterView.TranslateToAsync(0, 0, AnimationDuration, Easing.CubicInOut);Problem: The comment says "deadlock" but the actual issue is an infinite layout cycle / property changed loop. A deadlock implies mutual thread blocking, which is not what occurs here. The PR description itself correctly identifies this as "an infinite property changed cycle". This comment was flagged during review (as PRRT_kwDOD6PVWM5jdllo) but appears unresolved in the current code.
Recommendation:
// Previously caused an infinite layout update cycle on iOS .NET 10
await FooterView.TranslateToAsync(0, 0, AnimationDuration, Easing.CubicInOut);3. Redundant Interface Check in IsParentHandlingSafeArea()
File: src/Core/src/Platform/iOS/MauiView.cs
Lines: 401–403
_parentHandlesSafeArea = this.FindParent(x => x is MauiView mv
&& mv._appliesSafeAreaAdjustments
&& mv.View is ISafeAreaView or ISafeAreaView2) is not null;Problem: The condition mv.View is ISafeAreaView or ISafeAreaView2 is redundant. mv._appliesSafeAreaAdjustments is only ever set to true when RespondsToSafeArea() returns a non-empty SafeAreaPadding, which in turn only happens when View is ISafeAreaView2 or View is ISafeAreaView. So checking the interface again is unnecessary.
Recommendation:
_parentHandlesSafeArea = this.FindParent(x => x is MauiView mv
&& mv._appliesSafeAreaAdjustments) is not null;This is cleaner and more consistent with the encapsulation intent of _appliesSafeAreaAdjustments.
4. Cache Invalidation May Be Incomplete for Runtime SafeAreaEdges Changes
File: src/Core/src/Platform/iOS/MauiView.cs
Problem: _parentHandlesSafeArea is invalidated in SafeAreaInsetsDidChange() and MovedToWindow(). However, when a parent's SafeAreaEdges property changes at runtime (as tested in VerifyRuntimeSafeAreaEdgesChange()), neither of those events fires on the child. The child's _parentHandlesSafeArea cache may remain stale, returning an incorrect result until the next safe area insets change or view hierarchy change.
In practice, changing SafeAreaEdges triggers a layout invalidation, which leads to SafeAreaInsetsDidChange() being called on descendants (because layout recalculation causes the system to re-evaluate safe area insets). If this happens reliably in practice, the cache is effectively always fresh. The test VerifyRuntimeSafeAreaEdgesChange() verifies this scenario works.
Recommendation: Verify (or document) that changing SafeAreaEdges on a parent reliably triggers SafeAreaInsetsDidChange() on children. If there are edge cases where it doesn't (e.g., when the view is off-screen), consider also invalidating _parentHandlesSafeArea when the parent hierarchy is traversed and a stale result would matter.
This is a low-risk concern since the test covers the runtime toggle scenario.
5. Missing Newline at End of File
File: src/Controls/tests/TestCases.HostApp/Issues/Issue32586.cs
The file is missing a newline at the end (\ No newline at end of file in the diff). Minor style issue.
✅ Looks Good
- Caching pattern is well-designed and follows the existing
_scrollViewDescendantpattern — same nullablebool?approach, same invalidation points. - Cache invalidated in the right places — both
SafeAreaInsetsDidChange()andMovedToWindow()properly reset_parentHandlesSafeArea = null. - Fix is minimally invasive — only 29 additions and 1 deletion in production code (
MauiView.cs); all other additions are test code. - XML documentation is added for
IsParentHandlingSafeArea(), consistent with the surrounding code style. IsSoftInputHandledByParent()pattern is reused — the newIsParentHandlingSafeArea()follows the same pattern as the existing staticIsSoftInputHandledByParent()method.- Two distinct issues are fixed (Layout issue using TranslateToAsync causes infinite property changed cycle on iOS #32586 and [net10] iOS 18.6 crashing on navigating to a ContentPage with Padding set and Content set to a <Grid RowDefinitions="*,Auto"> with ScrollView on row 0 #33595) with both test pages and automated tests added for each.
Issue33595.csUI test is correctly guarded with#if IOSonly.
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
Two fixes: 1. post-ai-summary-comment.ps1: Remove legacy stdin reader ($input | Out-String) that blocks forever in non-interactive CI contexts when no state file is found. 2. ci-copilot.yml: Add state file existence check before calling the script (skip gracefully if missing), and add timeoutInMinutes: 5 as a safety net. Root cause: Build 13284089 (iOS, PR #32797) timed out at 180 min because the fallback step hung for 2+ hours reading from stdin.
|
We have an app that after upgrading to .net10 have had multiple layout cycle problems on iOS. None of these issues existed with .net9. We have experienced this as pages just being blank because of infinite layout loops when navigating to them. If i press pause when debugging I can see that the stacktrace always starts with something like The workaround have been all kinds of stuff.
The font problems seems to happen if the user set a text size in ios settings -> display & brightness that is not the default. We have one page which has had almost all of this problems. We have this page locked in landscape mode and use SafeAreaEdges.None on all the grids. I have a hard time figuring out what is actually causing this. Right now to find out which element is the problem I have to remove elements until it works I have two layout cycle problems right now and I've tried this PR but it didn't solve it. |
Two fixes: 1. post-ai-summary-comment.ps1: Remove legacy stdin reader ($input | Out-String) that blocks forever in non-interactive CI contexts when no state file is found. 2. ci-copilot.yml: Add state file existence check before calling the script (skip gracefully if missing), and add timeoutInMinutes: 5 as a safety net. Root cause: Build 13284089 (iOS, PR #32797) timed out at 180 min because the fallback step hung for 2+ hours reading from stdin.
Two fixes: 1. post-ai-summary-comment.ps1: Remove legacy stdin reader ($input | Out-String) that blocks forever in non-interactive CI contexts when no state file is found. 2. ci-copilot.yml: Add state file existence check before calling the script (skip gracefully if missing), and add timeoutInMinutes: 5 as a safety net. Root cause: Build 13284089 (iOS, PR #32797) timed out at 180 min because the fallback step hung for 2+ hours reading from stdin.
…tion counter When both a parent and child view respond to SafeArea (both have SafeAreaEdges = Container), an infinite layout cycle occurs: each view's layout change triggers the other to re-validate, creating an endless loop that freezes the app. Root cause: Both views apply SafeArea padding independently. Each layout pass invalidates ancestors, which triggers another layout pass, ad infinitum. Previous approach (PR #32797): Check if parent handles SafeArea via hierarchy walk. Problem: This silences ALL child SafeArea edges when parent handles ANY edge, breaking nested SafeArea scenarios where parent handles top and child independently handles bottom. This fix: Use a generation counter incremented on genuine SafeAreaInsetsDidChange events. Each view tracks the last generation where it invalidated ancestors. If already invalidated for current generation, skip re-invalidation and just arrange. Benefits: - Breaks the cycle: within a single SafeArea change event, each view only invalidates once - Preserves correct behavior: both parent and child can still apply their own SafeArea edges - Simpler logic: no hierarchy walking, just atomic counter check Test cases (Issue32586, Issue33595): - Nested Grid + VerticalStackLayout with SafeArea=Container - TranslateToAsync animation that previously triggered infinite cycle - Runtime SafeAreaEdges toggling Fixes #32586 Fixes #33595
…tion counter When both a parent and child view respond to SafeArea (both have SafeAreaEdges = Container), an infinite layout cycle occurs: each view's layout change triggers the other to re-validate, creating an endless loop that freezes the app. Root cause: Both views apply SafeArea padding independently. Each layout pass invalidates ancestors, which triggers another layout pass, ad infinitum. Previous approach (PR #32797): Check if parent handles SafeArea via hierarchy walk. Problem: This silences ALL child SafeArea edges when parent handles ANY edge, breaking nested SafeArea scenarios where parent handles top and child independently handles bottom. This fix: Use a generation counter incremented on genuine SafeAreaInsetsDidChange events. Each view tracks the last generation where it invalidated ancestors. If already invalidated for current generation, skip re-invalidation and just arrange. Benefits: - Breaks the cycle: within a single SafeArea change event, each view only invalidates once - Preserves correct behavior: both parent and child can still apply their own SafeArea edges - Simpler logic: no hierarchy walking, just atomic counter check Test cases (Issue32586, Issue33595): - Nested Grid + VerticalStackLayout with SafeArea=Container - TranslateToAsync animation that previously triggered infinite cycle - Runtime SafeAreaEdges toggling Fixes #32586 Fixes #33595
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 of the Issue:
This infinite loop appears to occur due to the combination of auto sizing calculations in the grid and SafeArea adjustments, where both the parent and child grids continuously recalculate their layouts.
In the user provided sample, there are two Grids (parent and child), and the default SafeArea handling behavior for a Grid is container. As a result, both the parent and child apply SafeArea logic concurrently, which can lead to the loop, particularly when the view is TranslateTo inside and outside the SafeArea region at runtime.
Description of Change:
Issues Fixed
Fixes #32586
Fixes #33595
Screenshot
Before-Fix.mov.mov
After-Fix.mov