Skip to content

Commit 1ec5e65

Browse files
Shalini-AshokanPureWeen
authored andcommitted
[Android] Fix WebView scrolling inside ScrollView (#33133)
<!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details WebView does not scroll when placed inside a ScrollView. The parent ScrollView intercepts vertical touch gestures, preventing the WebView from scrolling its internal content. ### Root Cause The parent ScrollView was intercepting all touch events without checking if the child WebView needed to scroll. This prevented the WebView from receiving touch events and handling its own scrolling. ### Description of Change Added touch event handling to prevent parent interception when WebView scrolls. When touch begins or continues, WebView requests exclusive control from parent. When touch ends or cancels, control returns to parent. This enables WebView scrolling while preserving normal parent-child interaction. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #32971 ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/12b3ca6e-582d-4a50-9ea1-f49027f2d907" >| <video src="https://github.com/user-attachments/assets/2fbfd03c-4432-49e9-8b2d-6e7643f57487">|
1 parent 0d6f188 commit 1ec5e65

4 files changed

Lines changed: 120 additions & 0 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
namespace Maui.Controls.Sample.Issues;
2+
3+
[Issue(IssueTracker.Github, 32971, "WebView content does not scroll when placed inside a ScrollView", PlatformAffected.Android)]
4+
public class Issue32971 : ContentPage
5+
{
6+
public Issue32971()
7+
{
8+
Label _scrollStateLabel = new Label
9+
{
10+
Text = "NotScrolled",
11+
AutomationId = "ScrollStateLabel",
12+
FontSize = 20,
13+
HorizontalTextAlignment = TextAlignment.Center,
14+
};
15+
16+
WebView _webView = new WebView
17+
{
18+
AutomationId = "TestWebView",
19+
HeightRequest = 600,
20+
VerticalOptions = LayoutOptions.Start,
21+
};
22+
23+
_webView.Source = new HtmlWebViewSource
24+
{
25+
Html = @"
26+
<!DOCTYPE html>
27+
<html>
28+
<head>
29+
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
30+
<style>
31+
body { font-family: Arial; padding: 20px; margin: 0; }
32+
.section { border: 2px solid #0066cc; padding: 20px; margin: 10px 0; background: #f0f8ff; min-height: 300px; }
33+
</style>
34+
</head>
35+
<body>
36+
<h1>WebView Scrolling Test</h1>
37+
<div class='section'><h2>Section 1</h2><p>Scroll down to test...</p></div>
38+
<div class='section'><h2>Section 2</h2><p>Keep scrolling...</p></div>
39+
<div class='section'><h2>Section 3</h2><p>More content...</p></div>
40+
<div class='section'><h2>Section 4</h2><p>Almost there...</p></div>
41+
<div class='section'><h2>Section 5</h2><p>Bottom reached!</p></div>
42+
</body>
43+
</html>"
44+
};
45+
46+
var checkButton = new Button
47+
{
48+
Text = "Check Scroll State",
49+
AutomationId = "CheckButton",
50+
};
51+
52+
checkButton.Clicked += async (s, e) =>
53+
{
54+
var result = await _webView.EvaluateJavaScriptAsync("Math.round(window.pageYOffset);");
55+
if (int.TryParse(result, out int scrollPos) && scrollPos > 50)
56+
{
57+
_scrollStateLabel.Text = "Scrolled";
58+
}
59+
};
60+
61+
var scrollView = new ScrollView
62+
{
63+
AutomationId = "TestScrollView",
64+
Content = new VerticalStackLayout
65+
{
66+
Children = { _scrollStateLabel, checkButton, _webView }
67+
}
68+
};
69+
70+
Content = scrollView;
71+
}
72+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using NUnit.Framework;
2+
using UITest.Appium;
3+
using UITest.Core;
4+
5+
namespace Microsoft.Maui.TestCases.Tests.Issues;
6+
7+
public class Issue32971 : _IssuesUITest
8+
{
9+
public override string Issue => "WebView content does not scroll when placed inside a ScrollView";
10+
11+
public Issue32971(TestDevice device) : base(device)
12+
{
13+
}
14+
15+
[Test]
16+
[Category(UITestCategories.WebView)]
17+
public void WebViewShouldScrollInsideScrollView()
18+
{
19+
App.WaitForElement("TestScrollView");
20+
App.ScrollDown("TestScrollView");
21+
App.Tap("CheckButton");
22+
var scrollStateLabel = App.FindElement("ScrollStateLabel").GetText();
23+
Assert.That(scrollStateLabel, Is.EqualTo("Scrolled"));
24+
}
25+
}

src/Core/src/Platform/Android/MauiWebView.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using Android.Content;
33
using Android.Graphics;
4+
using Android.Views;
45
using Android.Webkit;
56

67
namespace Microsoft.Maui.Platform
@@ -42,6 +43,27 @@ protected override void OnSizeChanged(int width, int height, int oldWidth, int o
4243
}
4344
}
4445

46+
public override bool OnTouchEvent(MotionEvent? e)
47+
{
48+
if (e == null)
49+
return false;
50+
51+
switch (e.Action)
52+
{
53+
case MotionEventActions.Down:
54+
case MotionEventActions.Move:
55+
Parent?.RequestDisallowInterceptTouchEvent(true);
56+
break;
57+
58+
case MotionEventActions.Up:
59+
case MotionEventActions.Cancel:
60+
Parent?.RequestDisallowInterceptTouchEvent(false);
61+
break;
62+
}
63+
64+
return base.OnTouchEvent(e);
65+
}
66+
4567
void IWebViewDelegate.LoadHtml(string? html, string? baseUrl)
4668
{
4769
_handler?.CurrentNavigationEvent = WebNavigationEvent.NewPage;

src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ override Microsoft.Maui.Platform.LayoutViewGroup.HasOverlappingRendering.get ->
1414
override Microsoft.Maui.Platform.WrapperView.HasOverlappingRendering.get -> bool
1515
override Microsoft.Maui.Platform.MauiHybridWebView.OnSizeChanged(int width, int height, int oldWidth, int oldHeight) -> void
1616
override Microsoft.Maui.Platform.MauiWebView.OnSizeChanged(int width, int height, int oldWidth, int oldHeight) -> void
17+
override Microsoft.Maui.Platform.MauiWebView.OnTouchEvent(Android.Views.MotionEvent? e) -> bool

0 commit comments

Comments
 (0)