Есть ли способ предотвратить распространение жестов смахивания из элемента управления на его родительский элемент управления в .NET MAUI?
В этом проекте я использую DXRangeSlider внутри TabView. Оба являются бесплатными элементами управления MAUI (на момент написания), созданными DevExpress. Тем не менее, любой перелистываемый элемент управления, определенный как содержимое для представления вкладки, вызывает эту проблему.
Когда TabView.SwipeEnabled = True вы можете провести влево или вправо по содержимому вкладки, чтобы перейти к предыдущей или следующей вкладке в последовательности. Если какое-либо содержимое вкладки содержит элементы управления, которые можно перелистывать, вы не можете пролистывать эти элементы управления без вызова действия пролистывания вкладки.
Я бы хотел, чтобы TabView игнорировал мой жест смахивания, когда жест смахивания нацелен на дочерний элемент управления.
Есть ли способ добиться этого?
В настройке XAML нет ничего сложного:
<dxcontrols:TabView>
<dxcontrols:TabViewItem>
...
</dxcontrols:TabViewItem>
<!-- Parent swipable control: -->
<dxcontrols:TabViewItem>
...
<!-- Child swipable control: -->
<dxeditors:DXRangeSlider/>
...
</dxcontrols:TabViewItem>
<dxcontrols:TabViewItem>
...
</dxcontrols:TabViewItem>
</dxcontrols:TabView>
Я считаю, что та же проблема возникнет при использовании MAUI Slider или любого элемента управления с распознавателями жестов смахивания внутри CarouselView, в котором включено смахивание.





Я считаю, что та же проблема возникнет при использовании слайдера MAUI или любого элемента управления с распознавателями жестов смахивания в CarouselView, в котором включено смахивание.
Да, есть та же проблема. И я могу решить эту проблему, добавив IOnTouchListener для собственного представления Android. И запретите передачу события прокрутки из дочернего представления в родительское.
Слушатель:
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;
}
}
А затем вы можете добавить Listener для слайдера в код или собственный обработчик.
1. В коде: слайдер имеет имя в xaml, например: <Slider x:Name = "slider">. И в коде позади:
protected override void OnHandlerChanged()
{
base.OnHandlerChanged();
#if ANDROID
(slider.Handler.PlatformView as Android.Widget.Seekbar)
.SetOnTouchListener(new SliderListener());
#endif
}
2. Установите его в настраиваемом обработчике: вы можете обратиться к официальному документу о Настроить элементы управления с помощью обработчиков. И сделайте это в методе ConnectHandler Custom Handler.
protected override void ConnectHandler(SeekBar platformView)
{
base.ConnectHandler(platformView);
platformView.SetOnTouchListener(new SliderListener());
}
Вы можете проверить исходный код DXRangeSlider или просто выполнить отладку, чтобы получить представление о платформе. А затем, используя тот же метод, чтобы решить проблему.
В дополнение к ответу ЛиюньЧжана:
Специально для элементов управления DX Slider (благодаря их центру поддержки) я выяснил, что у них есть события TapPressed и TapReleased, которые можно использовать для установки свойства TabView.SwipeEnabled в false при использовании ползунка и обратно в true при отпускании крана.
1. Просто установите события с помощью элемента управления DXSlider или DXRangeSlider:
<dxcontrols:TabView x:Name = "FilterTabView">
<dxcontrols:TabViewItem>
<!-- ... content ... -->
</dxcontrols:TabViewItem>
<dxcontrols:TabViewItem>
<dxeditors:DXRangeSlider
TapPressed = "DXRangeSlider_TapPressed"
TapReleased = "DXRangeSlider_TapReleased"/>
</dxcontrols:TabViewItem>
<dxcontrols:TabViewItem>
<!-- ... content ... -->
</dxcontrols:TabViewItem>
</dxcontrols:TabView>
2. Затем используйте обработчики событий, чтобы изменить TabView.SwipeEnabled в коде программной части:
private void DXRangeSlider_TapPressed(object sender, DevExpress.Maui.Core.DXTapEventArgs e)
{
FilterTabView.SwipeEnabled = false;
}
private void DXRangeSlider_TapReleased(object sender, DevExpress.Maui.Core.DXTapEventArgs e)
{
FilterTabView.SwipeEnabled = true;
}
Для MVVM вы можете использовать MCT EventToCommandBehavior вместо команд:
<dxeditors:DXRangeSlider>
<dxeditors:DXRangeSlider.Behaviors>
<toolkit:EventToCommandBehavior
EventName = "TapPressed"
Command = "{Binding TapPressedCommand}"/>
<toolkit:EventToCommandBehavior
EventName = "TapReleased"
Command = "{Binding TapReleasedCommand}"/>
</dxeditors:DXRangeSlider.Behaviors>
</dxeditors:DXRangeSlider>
Я считаю, что ответ Лиюньчжанса приближается к идеальному решению, потому что это более общий подход для всех элементов управления MAUI. Я просто подумал, что это может быть полезно для тех, кто использует те же элементы управления DX.
Рад узнать, что вы решили эту проблему, и спасибо, что поделились.
По крайней мере, для Android это помогает, большое спасибо за ваш ответ! Кроме того, специально для элементов управления ползунком DX я выяснил, что вы можете использовать их события
TapPressedиTapReleasedдля установкиTabView.SwipeEnabledtrue или false при использовании ползунка. Я создал свой собственный ответ, чтобы предложить другое решение, но я приму ваше, поскольку это более общий подход для всех элементов управления MAUI.