[Windows, Android] Fix ScrollView Content Not Removed When Set to Null#33069
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 33069Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 33069" |
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where setting ScrollView.Content to null on Android and Windows did not properly remove the existing content from the native view hierarchy, while iOS handled this correctly. The fix modifies the handler update methods to explicitly clear native children when PresentedContent is null, preventing memory leaks and visual inconsistencies.
Key Changes
- Android & Windows handlers: Restructured content update logic to handle null content by clearing native children before returning
- Added UI test: Created automated test to verify content removal and re-addition behavior across all platforms
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/Core/src/Handlers/ScrollView/ScrollViewHandler.Windows.cs | Refactored UpdateContentPanel to clear CachedChildren when content is set to null, ensuring proper cleanup on Windows |
| src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs | Refactored UpdateInsetView to call RemoveAllViews() when content is set to null, ensuring proper cleanup on Android |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33067.cs | Added NUnit UI test to verify ScrollView content removal and re-addition behavior |
| src/Controls/tests/TestCases.HostApp/Issues/Issue33067.cs | Added test page with interactive buttons to demonstrate and test the bug fix |
| { | ||
| currentPaddingLayer.CachedChildren.Clear(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Trailing whitespace should be removed from this empty line. This can be caught by running dotnet format before committing.
| var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext); | ||
|
|
||
| if (GetContentPanel(scrollViewer) is ContentPanel currentPaddingLayer) | ||
| if (currentPaddingLayer != null) |
There was a problem hiding this comment.
Inconsistent null check pattern. This should use is not null to match the pattern used elsewhere in this file (line 139) and maintain consistency with the rest of the codebase.
| if (currentPaddingLayer != null) | |
| if (currentPaddingLayer is not null) |
| @@ -0,0 +1,80 @@ | |||
| using System.Collections.ObjectModel; | |||
There was a problem hiding this comment.
The System.Collections.ObjectModel namespace is not used in this file and should be removed.
| using System.Collections.ObjectModel; |
| if (_originalContent != null) | ||
| { | ||
| _scrollView.Content = _originalContent; | ||
| } |
There was a problem hiding this comment.
The null check for _originalContent is unnecessary here because it's initialized as null! (null-forgiving operator) on line 10 and is always assigned a non-null value in CreateUI() before any button click can occur. This check can be simplified to just _scrollView.Content = _originalContent;
| if (_originalContent != null) | |
| { | |
| _scrollView.Content = _originalContent; | |
| } | |
| _scrollView.Content = _originalContent; |
|
@ -0,0 +1,485 @@ Review Feedback: PR #33069 - [Windows, Android] Fix ScrollView Content Not Removed When Set to NullRecommendation✅ Approve with Minor Suggestions Critical Fix: This PR correctly fixes a memory leak and visual bug where Android and Windows fail to remove ScrollView content when set to null. The fix aligns with iOS behavior and follows best practices. Recommended changes (non-blocking):
📋 Full PR Review DetailsSummaryThis PR fixes a memory leak and visual bug on Android and Windows where setting Impact: Prevents memory leaks in apps that dynamically change ScrollView content, especially in scenarios like tab navigation or conditional UI updates. Root Cause AnalysisThe ProblemThe original Android and Windows handlers had a critical flaw in their early-return logic: // OLD CODE (BROKEN) - Android
static void UpdateInsetView(IScrollView scrollView, IScrollViewHandler handler, ...)
{
if (scrollView.PresentedContent == null || handler.MauiContext == null)
{
return; // ❌ Returns WITHOUT touching the native view!
}
var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext);
// ... update logic
}What happens when setting
Why this is a bug:
Why iOS Works CorrectlyiOS handler ( // iOS CODE (CORRECT)
static void UpdateContentView(IScrollView scrollView, IScrollViewHandler handler)
{
var platformView = handler.PlatformView;
// ALWAYS remove existing content first
if (platformView.GetContentView() is { } currentContentPlatformView)
{
currentContentPlatformView.RemoveFromSuperview(); // ✅ Always clears first
changed = true;
}
// THEN add new content if present
if (scrollView.PresentedContent is { } content)
{
var platformContent = content.ToPlatform(mauiContext);
platformView.AddSubview(platformContent);
changed = true;
}
}Key insight: iOS separates removal from addition. It always removes existing content, then conditionally adds new content. The SolutionThis PR applies the iOS pattern to Android and Windows: Android (NEW CODE): static void UpdateInsetView(IScrollView scrollView, IScrollViewHandler handler, ...)
{
if (handler.MauiContext is null) // ✅ Only check infrastructure
{
return;
}
var currentPaddingLayer = FindInsetPanel(handler);
// ✅ Explicitly handle null case - REMOVE content
if (scrollView.PresentedContent is null)
{
currentPaddingLayer?.RemoveAllViews();
return;
}
// Only execute ToPlatform if content is not null
var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext);
// Update content if changed
if (currentPaddingLayer is not null)
{
if (currentPaddingLayer.ChildCount == 0 || currentPaddingLayer.GetChildAt(0) != nativeContent)
{
currentPaddingLayer.RemoveAllViews();
currentPaddingLayer.AddView(nativeContent);
}
}
else
{
InsertInsetView(handler, scrollView, nativeContent, crossPlatformLayout);
}
}Windows follows the same pattern with Code ReviewChanges MadeFiles Modified:
Android Changes AnalysisBefore (lines 196-218): if (scrollView.PresentedContent == null || handler.MauiContext == null)
{
return; // Problem: Never removes existing content
}
var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext);
if (FindInsetPanel(handler) is ContentViewGroup currentPaddingLayer)
{
if (currentPaddingLayer.ChildCount == 0 || currentPaddingLayer.GetChildAt(0) != nativeContent)
{
currentPaddingLayer.RemoveAllViews();
currentPaddingLayer.AddView(nativeContent);
}
}After (lines 196-229): if (handler.MauiContext is null) // ✅ Separated infrastructure check
{
return;
}
var currentPaddingLayer = FindInsetPanel(handler); // ✅ Find once, reuse
if (scrollView.PresentedContent is null) // ✅ Explicit null handling
{
currentPaddingLayer?.RemoveAllViews(); // ✅ Clean up
return;
}
var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext); // ✅ Safe to call
if (currentPaddingLayer is not null) // ✅ Changed from pattern matching
{
// Only update if content has changed or is missing
if (currentPaddingLayer.ChildCount == 0 || currentPaddingLayer.GetChildAt(0) != nativeContent)
{
currentPaddingLayer.RemoveAllViews();
currentPaddingLayer.AddView(nativeContent);
}
}
else
{
InsertInsetView(handler, scrollView, nativeContent, crossPlatformLayout);
}Key improvements:
Windows Changes AnalysisSame pattern applied to Windows:
Code Quality AssessmentStrengths:
Architecture:
Performance:
Security & Safety:
Test CoverageTests Included in PR ✅Test Page:
NUnit Test: [Test]
[Category(UITestCategories.ScrollView)]
public void VerifyScrollViewContentWhenSetToNull()
{
App.WaitForElement("SetNullButton");
App.Tap("SetNullButton");
App.WaitForNoElement("ContentLabel"); // ✅ Verifies content removed
App.Tap("AddContentButton");
App.WaitForElement("ContentLabel"); // ✅ Verifies content re-added
}Test quality: ✅ Good
What the Test Covers✅ Covered scenarios:
What the Test Doesn't Cover🟡 Edge cases not tested (non-critical but worth considering):
Assessment: The included test is sufficient for the bug fix. Additional edge case tests would be nice-to-have but not required for merge. Edge Cases AnalysisHandled Correctly ✅
Potential Concerns (Low Priority) 🟡
Consistency with MAUI CodebaseComparison with iOS HandlerThis PR brings Android/Windows into alignment with iOS:
Verdict: ✅ Excellent consistency - All platforms now use the same logical pattern. Pattern Usage in Other HandlersSimilar patterns in MAUI codebase:
Verdict: ✅ This PR follows established MAUI patterns. Issues FoundMust FixNone - Code is correct as written. Should Fix (Non-blocking suggestions)
Won't Fix (Intentional choices)
Approval Checklist
Additional NotesFor ReviewersThis is a straightforward bug fix that addresses:
The author:
Confidence level: Very High
For Merge DecisionRecommendation: Approve and merge Why merge:
Follow-up work (optional, separate issues):
Related Issues/PRsSimilar fixes in MAUI history:
Pattern: MAUI has historically had issues with null content handling. This PR continues the trend of fixing these systematically. Review Metadata
Summary for TeamThis is a clean bug fix that resolves a memory leak and visual inconsistency when setting The change is minimal, focused, and low-risk. Ready to merge. Decision: ✅ Ready to merge |
|
Hi @devanathan-vaithiyanathan could you please add this test? [Test]
public void ScrollViewInitializedWithNullContent()
{
// Test that ScrollView can be created with Content = null
// Verifies no crashes, proper layout
} |
@kubaflo , Thanks for suggestion, I've modified the test. |
I don't see any new commit. Am I missing something? |
|
@MartyIX @devanathan-vaithiyanathan thanks! |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
## What's Coming .NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 27 commits with various improvements, bug fixes, and enhancements. ## CollectionView - [iOS][CV2] Fix page can be dragged down, and it would cause an extra space between Header and EmptyView text by @devanathan-vaithiyanathan in #31840 <details> <summary>🔧 Fixes</summary> - [I8_Header_and_Footer_Null - The page can be dragged down, and it would cause an extra space between Header and EmptyView text.](#31465) </details> - [iOS] Fixed the Items not displayed properly in CarouselView2 by @Ahamed-Ali in #31336 <details> <summary>🔧 Fixes</summary> - [[iOS] Items are not updated properly in CarouselView2.](#31148) </details> ## Docs - Improve Controls Core API docs by @jfversluis in #33240 ## Editor - [iOS] Fixed an issue where an Editor with a small height inside a ScrollView would cause the entire page to scroll by @Tamilarasan-Paranthaman in #27948 <details> <summary>🔧 Fixes</summary> - [[iOS][Editor] An Editor that has not enough height and resides inside a ScrollView/CollectionView will scroll the entire page](#27750) </details> ## Image - [Android] Image control crashes on Android when image width exceeds height by @KarthikRajaKalaimani in #33045 <details> <summary>🔧 Fixes</summary> - [Image control crashes on Android when image width exceeds height](#32869) </details> ## Mediapicker - [Android 🤖] Add a log telling why the request is cancelled by @pictos in #33295 <details> <summary>🔧 Fixes</summary> - [MediaPicker.PickPhotosAsync throwing TaskCancelledException in net10-android](#33283) </details> ## Navigation - [Android] Fix for App Hang When PopModalAsync Is Called Immediately After PushModalAsync with Task.Yield() by @BagavathiPerumal in #32479 <details> <summary>🔧 Fixes</summary> - [App hangs if PopModalAsync is called after PushModalAsync with single await Task.Yield()](#32310) </details> - [iOS 26] Navigation hangs after rapidly open and closing new page using Navigation.PushAsync - fix by @kubaflo in #32456 <details> <summary>🔧 Fixes</summary> - [[iOS 26] Navigation hangs after rapidly open and closing new page using Navigation.PushAsync](#32425) </details> ## Pages - [iOS] Fix ContentPage BackgroundImageSource not working by @Shalini-Ashokan in #33297 <details> <summary>🔧 Fixes</summary> - [.Net MAUI- Page.BackgroundImageSource not working for iOS](#21594) </details> ## RadioButton - [Issue-Resolver] Fix #33264 - RadioButtonGroup not working with Collection View by @kubaflo in #33343 <details> <summary>🔧 Fixes</summary> - [RadioButtonGroup not working with CollectionView](#33264) </details> ## SafeArea - [Android] Fixed Label Overlapped by Android Status Bar When Using SafeAreaEdges="Container" in .NET MAUI by @NirmalKumarYuvaraj in #33285 <details> <summary>🔧 Fixes</summary> - [SafeAreaEdges works correctly only on the first tab in Shell. Other tabs have content colliding with the display cutout in the landscape mode.](#33034) - [Label Overlapped by Android Status Bar When Using SafeAreaEdges="Container" in .NET MAUI](#32941) - [[MAUI 10] Layout breaks on first navigation (Shell // route) until soft keyboard appears/disappears (Android + iOS)](#33038) </details> ## ScrollView - [Windows, Android] Fix ScrollView Content Not Removed When Set to Null by @devanathan-vaithiyanathan in #33069 <details> <summary>🔧 Fixes</summary> - [[Windows, Android] ScrollView Content Not Removed When Set to Null](#33067) </details> ## Searchbar - Fix Android crash when changing shared Drawable tint on Searchbar by @tritter in #33071 <details> <summary>🔧 Fixes</summary> - [[Android] Crash on changing Tint of Searchbar](#33070) </details> ## Shell - [iOS] - Fix Custom FlyoutIcon from Being Overridden to Default Color in Shell by @prakashKannanSf3972 in #27580 <details> <summary>🔧 Fixes</summary> - [Change the flyout icon color](#6738) </details> - [iOS] Fix Shell NavBarIsVisible updates when switching ShellContent by @Vignesh-SF3580 in #33195 <details> <summary>🔧 Fixes</summary> - [[iOS] Shell NavBarIsVisible is not updated when changing ShellContent](#33191) </details> ## Slider - [C] Fix Slider and Stepper property order independence by @StephaneDelcroix in #32939 <details> <summary>🔧 Fixes</summary> - [Slider Binding Initialization Order Causes Incorrect Value Assignment in XAML](#32903) - [Slider is very broken, Value is a mess when setting Minimum](#14472) - [Slider is buggy depending on order of properties](#18910) - [Stepper Value is incorrectly clamped to default min/max when using bindableproperties in MVVM pattern](#12243) - [[Issue-Resolver] Fix #32903 - Sliderbinding initialization order issue](#32907) </details> ## Stepper - [Windows] Maui Stepper: Clamp minimum and maximum value by @OomJan in #33275 <details> <summary>🔧 Fixes</summary> - [[Windows] Maui Stepper is not clamped to minimum or maximum internally](#33274) </details> - [iOS] Fixed the UIStepper Value from being clamped based on old higher MinimumValue - Candidate PR test failure fix- 33363 by @Ahamed-Ali in #33392 ## TabbedPage - [windows] Fixed Rapid change of selected tab results in crash. by @praveenkumarkarunanithi in #33113 <details> <summary>🔧 Fixes</summary> - [Rapid change of selected tab results in crash on Windows.](#32824) </details> ## Titlebar - [Mac] Fix TitleBar Content Overlapping with Traffic Light Buttons on Latest macOS Version by @devanathan-vaithiyanathan in #33157 <details> <summary>🔧 Fixes</summary> - [TitleBar Content Overlapping with Traffic Light Buttons on Latest macOS Version](#33136) </details> ## Xaml - Fix for Control does not update from binding anymore after MultiBinding.ConvertBack is called by @BagavathiPerumal in #33128 <details> <summary>🔧 Fixes</summary> - [Control does not update from binding anymore after MultiBinding.ConvertBack is called](#24969) - [The issue with the MultiBinding converter with two way binding mode does not work properly when changing the values.](#20382) </details> <details> <summary>🔧 Infrastructure (1)</summary> - Avoid KVO on CALayer by introducing an Apple PlatformInterop by @albyrock87 in #30861 </details> <details> <summary>🧪 Testing (2)</summary> - [Testing] Enable UITest Issue18193 on MacCatalyst by @NafeelaNazhir in #31653 <details> <summary>🔧 Fixes</summary> - [Test Issue18193 was disabled on Mac Catalyst](#27206) </details> - Set the CV2 handlers as the default by @Ahamed-Ali in #33177 </details> <details> <summary>📦 Other (3)</summary> - Update WindowsAppSDK to 1.8 by @mattleibow in #32174 <details> <summary>🔧 Fixes</summary> - [Update to WindowsAppSDK](#30858) </details> - Fix command dependency reentrancy by @simonrozsival in #33129 - Fix SafeArea AdjustPan handling and add AdjustNothing mode tests by @PureWeen via @Copilot in #33354 </details> **Full Changelog**: main...inflight/candidate
dotnet#33069) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies. ### Description of Change <!-- Enter description of the fix in this section --> In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes dotnet#33067 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5aff711f-7db8-4183-baa4-fb638d85860d" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/d010c2a8-50db-4ec8-8f8c-8f48d8b2ffbb" width="300" height="600"> |
Issue Details
When ScrollView.Content is set to null in .NET MAUI, iOS correctly removes the content, but Android and Windows do not. The previous content remains in the native view hierarchy, leading to memory leaks and visual inconsistencies.
Description of Change
In both platforms, the handler methods (UpdateInsetView on Android and UpdateContentPanel on Windows) were returning early when PresentedContent was null, without removing the existing native child views. As a result, stale views continued to remain attached.
Issues Fixed
Fixes #33067
Tested the behavior in the following platforms.
Before.mov
After.mov