Is there a way to prevent the propagation of swipe gestures from a control onto its parent control in .NET MAUI?
For this project I'm using a DXRangeSlider
within a TabView
. Both are free MAUI controls (at the time of writing) created by DevExpress. Nonetheless, any swipable control that is defined as content for the tab view, causes this issue.
When TabView.SwipeEnabled = True
you can swipe left or right on the tab content to navigate to the previous or next tab in the sequence. When any of the tab contents contain swipable controls, you cannot swipe these controls without calling the tab swipe action.
I'd like the TabView
to ignore my swipe gesture when the swipe gesture is targeting a child control.
Is there any way to achieve this?
The XAML setup is nothing too complicated:
<dxcontrols:TabView>
<dxcontrols:TabViewItem>
...
</dxcontrols:TabViewItem>
<!-- Parent swipable control: -->
<dxcontrols:TabViewItem>
...
<!-- Child swipable control: -->
<dxeditors:DXRangeSlider/>
...
</dxcontrols:TabViewItem>
<dxcontrols:TabViewItem>
...
</dxcontrols:TabViewItem>
</dxcontrols:TabView>
I believe the same issue would exist when using a MAUI Slider
or any control with swipe gesture recognizers within a CarouselView
that has swipe enabled.
I believe the same issue would exist when using a MAUI Slider or any control with swipe gesture recognizers within a CarouselView that has swipe enabled.
Yes, there is the same issue. And I can resolve it by adding IOnTouchListener
for the android native view. And prevent passing the swipe event from the child view to the parent view.
The Listener:
public class SliderListener : Java.Lang.Object, IOnTouchListener
{
public bool OnTouch(global::Android.Views.View v, MotionEvent e)
{
if (e.Action == MotionEventActions.Down || e.Action == MotionEventActions.Move)
{
v.Parent.RequestDisallowInterceptTouchEvent(true);
// prevent the parent view get the swipe event
}
else
{
v.Parent.RequestDisallowInterceptTouchEvent(false);
}
return false;
}
}
And then you can add the Listener
for the Slider in the code behind or custom handler.
1. In the code behind: the slider have a name in the xaml such as : <Slider x:Name="slider">
. And in the code behind:
protected override void OnHandlerChanged()
{
base.OnHandlerChanged();
#if ANDROID
(slider.Handler.PlatformView as Android.Widget.Seekbar)
.SetOnTouchListener(new SliderListener());
#endif
}
2. Set it in the custom handler: You can refer to the official document about Customize controls with handlers. And do this in the Custom Handler's ConnectHandler
method.
protected override void ConnectHandler(SeekBar platformView)
{
base.ConnectHandler(platformView);
platformView.SetOnTouchListener(new SliderListener());
}
You can check the source code about the DXRangeSlider
or just debug to get the platform view. And then using the same method to resolve the issue.