Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue36154.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 36154, "WebView inside SwipeView no longer responds to swipe gestures on Android", PlatformAffected.Android)]
public class Issue36154 : ContentPage
{
public Issue36154()
{
var directionLabel = new Label
{
AutomationId = "DirectionLabel",
Text = "Direction: — Offset: 0",
HorizontalOptions = LayoutOptions.Center,
Margin = new Thickness(4, 8),
FontSize = 13
};

var resultLabel = new Label
{
AutomationId = "ResultLabel",
Text = "Swipe result will appear here",
HorizontalOptions = LayoutOptions.Center,
Margin = new Thickness(4, 0, 4, 12),
FontSize = 13,
TextColor = Colors.Gray
};

var webView = new WebView
{
AutomationId = "TheWebView",
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
// Long scrollable page so vertical scroll can be verified
Source = new HtmlWebViewSource
{
Html = """
<html>
<body style="font-family:sans-serif;padding:16px">
<h3>Issue 36154 – WebView scroll test</h3>
<p>Scroll down to verify WebView vertical scrolling works inside SwipeView.</p>
<p>Then swipe left/right to reveal swipe items.</p>
<p>At the top edge, swipe down to reveal TopItems.</p>
<p>At the bottom edge, swipe up to reveal BottomItems.</p>
Comment thread
kubaflo marked this conversation as resolved.
""" + string.Concat(Enumerable.Range(1, 40).Select(i =>
$"<p>Line {i}: Lorem ipsum dolor sit amet consectetur adipiscing elit.</p>"))
+ "</body></html>"
Comment on lines +39 to +45
}
};

var swipeView = new SwipeView
{
AutomationId = "TheSwipeView",
Threshold = 80,

LeftItems = new SwipeItems(new[]
{
new SwipeItem
{
AutomationId = "LeftItem",
Text = "◀ LEFT",
BackgroundColor = Colors.MediumSeaGreen,
Command = new Command(() =>
{
resultLabel.Text = "LEFT item invoked";
})
}
})
{ Mode = SwipeMode.Execute, SwipeBehaviorOnInvoked = SwipeBehaviorOnInvoked.Close },

RightItems = new SwipeItems(new[]
{
new SwipeItem
{
AutomationId = "RightItem",
Text = "RIGHT ▶",
BackgroundColor = Colors.CornflowerBlue,
Command = new Command(() =>
{
resultLabel.Text = "RIGHT invoked!";
})
}
})
{ Mode = SwipeMode.Execute, SwipeBehaviorOnInvoked = SwipeBehaviorOnInvoked.Close },

Content = webView
};

swipeView.SwipeStarted += (s, e) =>
{
directionLabel.Text = $"Direction: {e.SwipeDirection} Offset: 0";
};

swipeView.SwipeChanging += (s, e) =>
directionLabel.Text = $"Direction: {e.SwipeDirection} Offset: {e.Offset:F0}";

swipeView.SwipeEnded += (s, e) =>
{
directionLabel.Text = $"Direction: {e.SwipeDirection} Open: {e.IsOpen}";
};

Content = new Grid
{
RowDefinitions =
[
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Star },
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto },
],
Children =
{
new Label
{
Text = "Swipe on WebView · scroll mid-page · swipe at edges",
HorizontalOptions = LayoutOptions.Center,
Margin = new Thickness(8),
FontSize = 13,
FontAttributes = FontAttributes.Bold
}.Row(0),

swipeView.Row(1),
directionLabel.Row(2),
resultLabel.Row(3)
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue36154 : _IssuesUITest
{
public Issue36154(TestDevice testDevice) : base(testDevice)
{
}

public override string Issue => "WebView inside SwipeView no longer responds to swipe gestures on Android";

// Verify that swiping left on the WebView reveals the Right swipe items
[Test]
[Category(UITestCategories.SwipeView)]
public void Issue36154SwipeViewShouldRevealItems()
{
#if WINDOWS
// WinUI cannot locate SwipeView through WebDriver, so use its WebView child for the gesture coordinates.
const string swipeTarget = "TheWebView";
#else
const string swipeTarget = "TheSwipeView";
#endif
var rect = App.WaitForElement(swipeTarget).GetRect();
var centerX = rect.X + rect.Width / 2;
var centerY = rect.Y + rect.Height / 2;

// Swipe left (finger moves left) → reveals RightItems
App.DragCoordinates(centerX, centerY, centerX - 200, centerY);

Assert.That(App.WaitForElement("ResultLabel").GetText(), Is.EqualTo("RIGHT invoked!"));
Comment on lines +30 to +33
}
}
16 changes: 16 additions & 0 deletions src/Core/src/Platform/Android/MauiSwipeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ bool ShouldInterceptScrollChildrenTouch(SwipeDirection swipeDirection)
if (_contentView is null || _initialPoint is null)
return false;

if (_contentView is AWebView contentWebView)
{
return ShouldInterceptWebViewTouch(contentWebView, swipeDirection);
}

var viewGroup = _contentView as ViewGroup;

if (viewGroup is not null)
Expand Down Expand Up @@ -166,6 +171,17 @@ bool ShouldInterceptScrollChildrenTouch(SwipeDirection swipeDirection)
return true;
}

// Determines whether the SwipeView should intercept touch events when the content is a WebView, based on the WebView's scroll position and the swipe direction.
static bool ShouldInterceptWebViewTouch(AWebView webView, SwipeDirection swipeDirection) =>
swipeDirection switch
Comment thread
kubaflo marked this conversation as resolved.
{
SwipeDirection.Right => !webView.CanScrollHorizontally(-1), // at left edge
SwipeDirection.Left => !webView.CanScrollHorizontally(1), // at right edge
SwipeDirection.Down => !webView.CanScrollVertically(-1), // at top
SwipeDirection.Up => !webView.CanScrollVertically(1), // at bottom
_ => true,
};
Comment on lines +174 to +183

static bool ShouldInterceptScrollChildrenTouch(ViewGroup scrollView, bool isHorizontal)
{
AView? scrollViewContent = scrollView.GetChildAt(0);
Expand Down
12 changes: 11 additions & 1 deletion src/Core/src/Platform/Android/MauiWebView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class MauiWebView : WebView, IWebViewDelegate

readonly WebViewHandler _handler;
readonly Rect _clipRect;
bool _hasSwipeViewParent;

public MauiWebView(WebViewHandler handler, Context context) : base(context)
{
Expand All @@ -37,6 +38,8 @@ protected override void OnAttachedToWindow()
// Re-evaluate ClipBounds when re-parented (e.g., wrapped in WrapperView for shadow)
UpdateClipBounds(Width, Height);

_hasSwipeViewParent = ((View)this).GetParentOfType<MauiSwipeView>() is not null;

if (RefreshViewWebViewScrollCapture.IsInsideMauiSwipeRefreshLayout(this))
{
RefreshViewWebViewScrollCapture.Attach(this);
Expand All @@ -55,6 +58,7 @@ protected override void OnDetachedFromWindow()
{
RefreshViewWebViewScrollCapture.Detach(this);
base.OnDetachedFromWindow();
_hasSwipeViewParent = false;
}

void UpdateClipBounds(int width, int height)
Expand Down Expand Up @@ -93,7 +97,13 @@ public override bool OnTouchEvent(MotionEvent? e)
{
case MotionEventActions.Down:
case MotionEventActions.Move:
Parent?.RequestDisallowInterceptTouchEvent(true);
// Do not request disallow intercept when inside a SwipeView — that would set
// FLAG_DISALLOW_INTERCEPT on the SwipeView and prevent it from detecting
// swipe gestures
if (!_hasSwipeViewParent)
{
Parent?.RequestDisallowInterceptTouchEvent(true);
}
break;

case MotionEventActions.Up:
Expand Down
Loading