Предотвратить распространение жестов пролистывания на родительские элементы управления в .NET MAUI?

Есть ли способ предотвратить распространение жестов смахивания из элемента управления на его родительский элемент управления в .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, в котором включено смахивание.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
103
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я считаю, что та же проблема возникнет при использовании слайдера 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 или просто выполнить отладку, чтобы получить представление о платформе. А затем, используя тот же метод, чтобы решить проблему.

По крайней мере, для Android это помогает, большое спасибо за ваш ответ! Кроме того, специально для элементов управления ползунком DX я выяснил, что вы можете использовать их события TapPressed и TapReleased для установки TabView.SwipeEnabled true или false при использовании ползунка. Я создал свой собственный ответ, чтобы предложить другое решение, но я приму ваше, поскольку это более общий подход для всех элементов управления MAUI.

Al John 12.06.2024 22:36

В дополнение к ответу ЛиюньЧжана:

Специально для элементов управления 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.

Рад узнать, что вы решили эту проблему, и спасибо, что поделились.

Liyun Zhang - MSFT 13.06.2024 05:50

Другие вопросы по теме