From a90cf35fb407d134ad3300d484bc7c90411e4b0e Mon Sep 17 00:00:00 2001 From: dominiktulak Date: Fri, 5 Dec 2025 14:10:10 +0100 Subject: [PATCH 1/2] Fix TabView touch interception for Android 15+ --- .../SfHorizontalContent.Android.cs | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs b/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs index 05413c7c..731885bc 100644 --- a/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs +++ b/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs @@ -19,6 +19,10 @@ internal partial class SfHorizontalContent double _moveX; double _moveY; + // Flag set to true when horizontal movement exceeds threshold and is greater than vertical movement, + // indicating this should be processed as a swipe gesture rather than a tap + bool _shouldProcessTouchForSwipe; + // Constants for touch movement thresholds const double VerticalScrollThreshold = 5; const double HorizontalScrollThreshold = 15; @@ -47,11 +51,13 @@ internal override bool OnInterceptTouchEvent(MotionEvent? motionEvent) _downX = motionEvent.GetX(); _downY = motionEvent.GetY(); _initialPoint = currenTouchPoint; + _shouldProcessTouchForSwipe = false; return false; } case MotionEventActions.Up: { _initialPoint = new Point(0, 0); + _shouldProcessTouchForSwipe = false; break; } case MotionEventActions.Move: @@ -59,15 +65,20 @@ internal override bool OnInterceptTouchEvent(MotionEvent? motionEvent) _moveX = motionEvent.GetX(); _moveY = motionEvent.GetY(); - // Check for vertical scrolling threshold - if (Math.Abs(_downY - _moveY) > VerticalScrollThreshold && Math.Abs(_downX - _moveX) < HorizontalScrollThreshold) + double horizontalDelta = Math.Abs(_downX - _moveX); + double verticalDelta = Math.Abs(_downY - _moveY); + + // Check for vertical scrolling threshold - don't intercept vertical scrolls + if (verticalDelta > VerticalScrollThreshold && horizontalDelta < HorizontalScrollThreshold) { return false; } - // Handle initial touch interaction - if (!_isPressed && Math.Abs(_downY - _moveY) != 0 && Math.Abs(_downX - _moveX) != 0) + // Only intercept if horizontal movement exceeds threshold and is greater than vertical movement + // This ensures taps with slight finger movement are not treated as swipes + if (!_isPressed && horizontalDelta > HorizontalScrollThreshold && horizontalDelta > verticalDelta) { + _shouldProcessTouchForSwipe = true; OnHandleTouchInteraction(PointerActions.Pressed, _initialPoint); return true; } @@ -85,6 +96,11 @@ internal override bool OnInterceptTouchEvent(MotionEvent? motionEvent) /// Pointer event arguments containing touch action and point. void ITouchListener.OnTouch(PointerEventArgs e) { + if (!_shouldProcessTouchForSwipe) + { + return; + } + switch (e.Action) { case PointerActions.Pressed: @@ -105,10 +121,11 @@ void ITouchListener.OnTouch(PointerEventArgs e) { // Handle the release action OnHandleTouchInteraction(PointerActions.Released, e.TouchPoint); + _shouldProcessTouchForSwipe = false; break; } } } #endregion } -} \ No newline at end of file +} From 2429be1dd9b5376ea5146fbc8ea052859a90f072 Mon Sep 17 00:00:00 2001 From: dominiktulak Date: Mon, 8 Dec 2025 09:07:31 +0100 Subject: [PATCH 2/2] Flag reset on MotionEventAction.Cancel --- .../Control/HorizontalContent/SfHorizontalContent.Android.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs b/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs index 731885bc..2610f425 100644 --- a/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs +++ b/maui/src/TabView/Control/HorizontalContent/SfHorizontalContent.Android.cs @@ -82,8 +82,13 @@ internal override bool OnInterceptTouchEvent(MotionEvent? motionEvent) OnHandleTouchInteraction(PointerActions.Pressed, _initialPoint); return true; } + break; } + case MotionEventActions.Cancel: + { + _shouldProcessTouchForSwipe = false; break; + } } }