diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyWebViewStaysWithinGridCell.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyWebViewStaysWithinGridCell.png new file mode 100644 index 000000000000..59b9aec867c2 Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/VerifyWebViewStaysWithinGridCell.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue32030.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue32030.cs new file mode 100644 index 000000000000..c953c54130a6 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue32030.cs @@ -0,0 +1,60 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 32030, "Android - WebView in a grid expands beyond it's cell", PlatformAffected.Android)] + +public class Issue32030 : ContentPage +{ + WebView webView; + + public Issue32030() + { + // Create Grid + var grid = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = new GridLength(50) }, + new RowDefinition { Height = GridLength.Star }, + new RowDefinition { Height = new GridLength(50) } + } + }; + + // Create "above webview" Label + var topLabel = new Label + { + Text = "Above webview", + AutomationId = "TopLabel", + HorizontalTextAlignment = TextAlignment.Center + }; + grid.Add(topLabel); + Grid.SetRow(topLabel, 0); + + // Create WebView + webView = new WebView + { + BackgroundColor = Colors.BurlyWood, + Source = new HtmlWebViewSource + { + Html = @"

Initial Content

" + } + }; + grid.Add(webView); + Grid.SetRow(webView, 1); + + var button = new Button + { + Text = "Click Me", + AutomationId = "BottomButton", + }; + + button.Clicked += (s, e) => + { + webView.Source = null; + }; + grid.Add(button); + Grid.SetRow(button, 2); + + // Set the grid as the page content + Content = grid; + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32030.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32030.cs new file mode 100644 index 000000000000..12c61f4142a8 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32030.cs @@ -0,0 +1,22 @@ +#if ANDROID //This is Android specific issue +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; +public class Issue32030 : _IssuesUITest +{ + public Issue32030(TestDevice device) : base(device) { } + + public override string Issue => "Android - WebView in a grid expands beyond it's cell"; + [Test] + [Category(UITestCategories.WebView)] + public void VerifyWebViewStaysWithinGridCell() + { + App.WaitForElement("BottomButton"); + App.Tap("BottomButton"); + App.WaitForElement("BottomButton"); + VerifyScreenshot(); + } +} +#endif diff --git a/src/Core/src/Platform/Android/MauiWebViewClient.cs b/src/Core/src/Platform/Android/MauiWebViewClient.cs index ee6eb9f021e6..b24f3ab6aa13 100644 --- a/src/Core/src/Platform/Android/MauiWebViewClient.cs +++ b/src/Core/src/Platform/Android/MauiWebViewClient.cs @@ -57,7 +57,8 @@ public override void OnPageFinished(WebView? view, string? url) bool navigate = _navigationResult != WebNavigationResult.Failure || !GetValidUrl(url).Equals(_lastUrlNavigatedCancel, StringComparison.OrdinalIgnoreCase); _lastUrlNavigatedCancel = _navigationResult == WebNavigationResult.Cancel ? url : null; - if (navigate) + // Skip Navigated event for about:blank to prevent unwanted events when Source is null + if (navigate && !IsBlankNavigation(url)) handler.VirtualView.Navigated(handler.CurrentNavigationEvent, GetValidUrl(url), _navigationResult); handler.SyncPlatformCookiesToVirtualView(url); @@ -96,6 +97,17 @@ public override bool OnRenderProcessGone(WebView? view, RenderProcessGoneDetail? bool NavigatingCanceled(string? url) => !_handler.TryGetTarget(out var handler) || handler.NavigatingCanceled(url); + static bool IsBlankNavigation(string? url) + { + // Null/empty URLs are handled by the early return in OnPageFinished, + // so we only need to check for the explicit "about:blank" URL + if (string.IsNullOrWhiteSpace(url)) + return false; + + // Check if URL is about:blank (case insensitive) + return string.Equals(url.Trim(), "about:blank", StringComparison.OrdinalIgnoreCase); + } + static string GetValidUrl(string? url) { if (string.IsNullOrEmpty(url)) diff --git a/src/Core/src/Platform/Android/WebViewExtensions.cs b/src/Core/src/Platform/Android/WebViewExtensions.cs index 7ab41a2789c4..f09cd7397f23 100644 --- a/src/Core/src/Platform/Android/WebViewExtensions.cs +++ b/src/Core/src/Platform/Android/WebViewExtensions.cs @@ -25,6 +25,11 @@ public static void UpdateSource(this AWebView platformWebView, IWebView webView, platformWebView.UpdateCanGoBackForward(webView); } } + else + { + // Load about:blank when source is null to ensure proper layout bounds + platformWebView.LoadUrl("about:blank"); + } } public static void UpdateSettings(this AWebView platformWebView, IWebView webView, bool javaScriptEnabled, bool domStorageEnabled)