diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue33067.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue33067.cs new file mode 100644 index 000000000000..2dd1044ec09c --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue33067.cs @@ -0,0 +1,80 @@ +using System.Collections.ObjectModel; + +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 33067, "[Windows, Android] ScrollView Content Not Removed When Set to Null", PlatformAffected.Android | PlatformAffected.UWP)] + +public class Issue33067 : ContentPage +{ + ScrollView _scrollView = null!; + Label _originalContent = null!; + Button _setNullButton = null!; + Button _addContentButton = null!; + + public Issue33067() + { + CreateUI(); + } + + void CreateUI() + { + // Create the original content label + _originalContent = new Label + { + Text = "This is a sample label inside the ScrollView that can be set to null and added back.", + Padding = new Thickness(20), + AutomationId = "ContentLabel", + FontSize = 16 + }; + + // Create the ScrollView + _scrollView = new ScrollView + { + BackgroundColor = Colors.LightGray, + HeightRequest = 300, + Content = null + }; + + // Create the "Set Content to Null" button + _setNullButton = new Button + { + Text = "Set Content to Null", + AutomationId = "SetNullButton" + }; + _setNullButton.Clicked += OnSetContentNullClicked; + + // Create the "Add Content" button + _addContentButton = new Button + { + Text = "Add Content", + AutomationId = "AddContentButton" + }; + _addContentButton.Clicked += OnAddContentClicked; + + // Create the main layout + var layout = new VerticalStackLayout + { + Spacing = 20, + Padding = new Thickness(30), + Children = { _setNullButton, _addContentButton, _scrollView } + }; + + // Set the content of the page + Content = layout; + } + + void OnSetContentNullClicked(object sender, EventArgs e) + { + // Set ScrollView content to null + _scrollView.Content = null; + } + + void OnAddContentClicked(object sender, EventArgs e) + { + // Restore the original content + if (_originalContent != null) + { + _scrollView.Content = _originalContent; + } + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33067.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33067.cs new file mode 100644 index 000000000000..45692b1ac65e --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33067.cs @@ -0,0 +1,30 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; +public class Issue33067 : _IssuesUITest +{ + public Issue33067(TestDevice device) : base(device) { } + + public override string Issue => "[Windows, Android] ScrollView Content Not Removed When Set to Null"; + + [Test, Order(1)] + [Category(UITestCategories.ScrollView)] + public void VerifyScrollViewContentShouldNull() + { + App.WaitForElement("SetNullButton"); + App.WaitForNoElement("ContentLabel"); + } + + [Test, Order(2)] + [Category(UITestCategories.ScrollView)] + public void VerifyScrollViewContentWhenSetToNull() + { + App.WaitForElement("SetNullButton"); + App.Tap("AddContentButton"); + App.WaitForElement("ContentLabel"); + App.Tap("SetNullButton"); + App.WaitForNoElement("ContentLabel"); + } +} \ No newline at end of file diff --git a/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs b/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs index a2ed1e09ec31..6b836a33ac5a 100644 --- a/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs +++ b/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs @@ -196,15 +196,26 @@ The methods below exist to support inserting/updating the extra padding/margin l static void UpdateInsetView(IScrollView scrollView, IScrollViewHandler handler, ICrossPlatformLayout crossPlatformLayout) { - if (scrollView.PresentedContent == null || handler.MauiContext == null) + if (handler.MauiContext is null) { return; } + // Find existing inset panel once + var currentPaddingLayer = FindInsetPanel(handler); + + // If PresentedContent is null, clean up any existing content and return + if (scrollView.PresentedContent is null) + { + currentPaddingLayer?.RemoveAllViews(); + return; + } + var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext); - if (FindInsetPanel(handler) is ContentViewGroup currentPaddingLayer) + if (currentPaddingLayer is not null) { + // Only update if content has changed or is missing if (currentPaddingLayer.ChildCount == 0 || currentPaddingLayer.GetChildAt(0) != nativeContent) { currentPaddingLayer.RemoveAllViews(); diff --git a/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Windows.cs b/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Windows.cs index 1bfe2081418e..8a3214733212 100644 --- a/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Windows.cs +++ b/src/Core/src/Handlers/ScrollView/ScrollViewHandler.Windows.cs @@ -125,21 +125,34 @@ The methods below exist to support inserting/updating the padding/margin panel. static void UpdateContentPanel(IScrollView scrollView, IScrollViewHandler handler, ICrossPlatformLayout crossPlatformLayout) { - if (scrollView.PresentedContent == null || handler.MauiContext == null) + if (handler.MauiContext is null) { return; } var scrollViewer = handler.PlatformView; + var currentPaddingLayer = GetContentPanel(scrollViewer); + + // If PresentedContent is null, clean up any existing content and return + if (scrollView.PresentedContent is null) + { + if (currentPaddingLayer is not null) + { + currentPaddingLayer.CachedChildren.Clear(); + } + + return; + } + var nativeContent = scrollView.PresentedContent.ToPlatform(handler.MauiContext); - if (GetContentPanel(scrollViewer) is ContentPanel currentPaddingLayer) + if (currentPaddingLayer is not null) { + // Only update if content has changed or is missing if (currentPaddingLayer.CachedChildren.Count == 0 || currentPaddingLayer.CachedChildren[0] != nativeContent) { currentPaddingLayer.CachedChildren.Clear(); currentPaddingLayer.CachedChildren.Add(nativeContent); - } } else