Home > database >  dotnet maui swipe gestures not working on device, but working in emulator
dotnet maui swipe gestures not working on device, but working in emulator

Time:01-19

I have been trying to find a solution for swipe gestures not working on devices but working fine in emulator. In visual studio running android 33.x on x64 platform emulator swipe gestures work. But on hardware device it does not at all.

Tap gestures are working on device and emulator.

Here is xaml code

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:model="clr-namespace:NerdNewsNavigator2.Model"
             xmlns:viewmodel="clr-namespace:NerdNewsNavigator2.ViewModel"
             x:Class="NerdNewsNavigator2.View.ShowPage"
             x:DataType="viewmodel:ShowViewModel"
             Title="">
    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="{OnPlatform Android=False,iOS=False, WinUI=True}">
        </BackButtonBehavior>
    </Shell.BackButtonBehavior>
    <CollectionView  ItemsSource="{Binding Shows}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="model:Show">
                <Frame WidthRequest="{OnPlatform Android=375, iOS=375, WinUI=800}" 
                       BackgroundColor="White" 
                       Padding="10">
                    <Frame.GestureRecognizers>
                        <SwipeGestureRecognizer Direction="Left" 
                            Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:ShowViewModel}}, Path=SwipedGestureCommand}" 
                            CommandParameter="{Binding Url}"/>
                        <TapGestureRecognizer 
                            Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:ShowViewModel}}, Path=TapCommand}" 
                            CommandParameter="{Binding Url}"/>
                    </Frame.GestureRecognizers>
                    <StackLayout VerticalOptions="Start" Spacing="10" Padding="10">
                        <Label Text="{Binding Title}" 
                               HorizontalTextAlignment="Center" 
                               TextColor="Black"  
                               FontSize="12"  
                               FontAttributes="Bold"
                               LineBreakMode="WordWrap"/>
                        <Image Aspect="AspectFill" Source="{Binding Image}" HeightRequest="{OnPlatform WinUI=400}">
                        </Image>
                        <Label Text="{Binding Description}" 
                               MaximumHeightRequest="{OnPlatform WinUI=1200}" 
                               FontSize="10" 
                               LineBreakMode="WordWrap" 
                               TextColor="Black" 
                               TextType="Html">
                        </Label>
                    </StackLayout>
                </Frame>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>


Here is c# code for page:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.ObjectModel;
using CodeHollow.FeedReader;
using CodeHollow.FeedReader.Feeds.Itunes;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NerdNewsNavigator2.Model;
using NerdNewsNavigator2.View;

namespace NerdNewsNavigator2.ViewModel;

[QueryProperty("Url", "Url")]
public partial class ShowViewModel : ObservableObject
{
    #region Properties
    public ObservableCollection<Show> Shows { get; set; } = new();
    #endregion

    public string Url
    {
        set
        {
            this.Shows = ShowViewModel.GetShow(value);
            OnPropertyChanged(nameof(Shows));
        }
    }
    #region GetShow
    private static ObservableCollection<Show> GetShow(string url)
    {
        ObservableCollection<Show> result = new();
        try
        {
            var feed = FeedReader.ReadAsync(url);
            foreach (var item in feed.Result.Items)
            {
                Show show = new()
                {
                    Title = item.Title,
                    Description = item.Description,
                    Image = item.GetItunesItem().Image.Href,
                    Url = item.Id
                };
                result.Add(show);
            }
            return result;
        }
        catch
        {
            Show show = new()
            {
                Title = string.Empty,
            };
            result.Add(show);
            return result;
        }
    }
    #endregion
    [RelayCommand]
    async Task SwipedGesture(string Url) => await Shell.Current.GoToAsync($"{nameof(PodcastPage)}?Url={Url}");

    [RelayCommand]
    async Task Tap(string Url) => await Shell.Current.GoToAsync($"{nameof(PlayPodcastPage)}?Url={Url}");
}

Any suggestions on how to fix this? Or is it a problem with maui? I am going to try default config for swipe gestures and modify post after I test. I wanted to use url variable to go back using viewmodel. But all I need is a swipe left to go back. This may be I just can't code this way but I don't understand why it works in emulator and not on device.

CodePudding user response:

There is something seriously wrong with it, that failed me on several occasions in the last months.

Here for example: https://github.com/dotnet/maui/issues/7403

It is working in some cases, you cant write normally custom controls however.

Try adding it, as the very first example, here: https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/gestures/swipe?view=net-maui-7.0

Also, Tap gesture will fire anyway. (This is why you will see many swipe controls, to have double tap effect, not tap).

CodePudding user response:

This is a working example. It works on Windows, Android emulator, and Android devices. I don't know about iOS or Mac. I do not have a developer account. My sample solution to swipe gestures with Maui

SwipeGestures.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewmodel="clr-namespace:SwipeGesturesSample.ViewModel"
             xmlns:model="clr-namespace:SwipeGesturesSample.Model"
             x:DataType="viewmodel:SwipeGesturesViewModel"
             x:Class="SwipeGesturesSample.View.SwipeGesturesPage"
             Title="SwipeGesturesPage">
    <StackLayout BackgroundColor="White" Padding="20" WidthRequest="375">
        <StackLayout.GestureRecognizers>
            <SwipeGestureRecognizer
                  Direction="Right" 
                Swiped="SwipedGesture" />
            <SwipeGestureRecognizer
                  Direction="Left" 
                Swiped="SwipedGesture" />
            <SwipeGestureRecognizer
                  Direction="Down" 
                Swiped="SwipedGesture" />
            <SwipeGestureRecognizer
                  Direction="Up" 
                Swiped="SwipedGesture" />
        </StackLayout.GestureRecognizers>
        <Label
            TextColor="Black"
            FontSize="20"
            x:Name="Right"
            HorizontalOptions="Center"
            Text="StackLayout Example: Swipe Right"
            SemanticProperties.Hint=""/>
        <Label
            TextColor="Black"
            FontSize="20"
            x:Name="Left"
            HorizontalOptions="Center"
            Text="StackLayout Example: Swipe Left"
            SemanticProperties.Hint=""/>
        <Label
            TextColor="Black"
            FontSize="20"
            x:Name="Up"
            HorizontalOptions="Center"
            Text="StackLayout Example: Swipe Up"
            SemanticProperties.Hint=""/>
        <Label
            TextColor="Black"
            FontSize="20"
            x:Name="Down"
            HorizontalOptions="Center"
            Text="StackLayout Example: Swipe Down"
            SemanticProperties.Hint=""/>
    </StackLayout>
</ContentPage>

code behind: SwipeGesturesPage.xaml.cs

using SwipeGesturesSample.Model;
using SwipeGesturesSample.ViewModel;

namespace SwipeGesturesSample.View;

public partial class SwipeGesturesPage : ContentPage
{
    Data data = new();
    public SwipeGesturesPage(SwipeGesturesViewModel viewmodel)
    {
        InitializeComponent();
        data.swipeTop = 0;
        data.swipeLeft = 0;
        data.swipeRight = 0;
        data.swipeBottom= 0;
       
        BindingContext= viewmodel;
    }
    private void SwipedGesture(object sender, SwipedEventArgs e)
    {
        switch (e.Direction)
        {
            case SwipeDirection.Up:
                data.swipeTop  = 1;
                Up.Text = $"Gestured up {data.swipeTop}";
                SemanticScreenReader.Announce(Up.Text);
                break;
            case SwipeDirection.Down:
                data.swipeBottom  = 1;
                Down.Text = $"Gestured down {data.swipeBottom}";
                SemanticScreenReader.Announce(Down.Text);
                break;
            case SwipeDirection.Left:
                data.swipeLeft  = 1;
                Left.Text = $"Gestured left {data.swipeLeft}";
                SemanticScreenReader.Announce(Left.Text);
                break;
            case SwipeDirection.Right:
                data.swipeRight  = 1;
                Right.Text = $"Gestured right {data.swipeRight}";
                SemanticScreenReader.Announce(Right.Text);
                break;
        }
    }
}

Data file: Data.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SwipeGesturesSample.Model;

public class Data
{
    public int number { get; set; } 
    public int swipeLeft { get; set; }
    public int swipeRight { get; set;}
    public int swipeTop { get; set;}
    public int swipeBottom { get; set;}
}

using SwipeGesturesSample.Model;
using SwipeGesturesSample.ViewModel;

namespace SwipeGesturesSample.View;

public partial class SwipeGesturesPage : ContentPage
{
    Data data = new();
    public SwipeGesturesPage(SwipeGesturesViewModel viewmodel)
    {
        InitializeComponent();
        data.swipeTop = 0;
        data.swipeLeft = 0;
        data.swipeRight = 0;
        data.swipeBottom= 0;
       
        BindingContext= viewmodel;
    }
    private void SwipedGesture(object sender, SwipedEventArgs e)
    {
        switch (e.Direction)
        {
            case SwipeDirection.Up:
                data.swipeTop  = 1;
                Up.Text = $"Gestured up {data.swipeTop}";
                SemanticScreenReader.Announce(Up.Text);
                break;
            case SwipeDirection.Down:
                data.swipeBottom  = 1;
                Down.Text = $"Gestured down {data.swipeBottom}";
                SemanticScreenReader.Announce(Down.Text);
                break;
            case SwipeDirection.Left:
                data.swipeLeft  = 1;
                Left.Text = $"Gestured left {data.swipeLeft}";
                SemanticScreenReader.Announce(Left.Text);
                break;
            case SwipeDirection.Right:
                data.swipeRight  = 1;
                Right.Text = $"Gestured right {data.swipeRight}";
                SemanticScreenReader.Announce(Right.Text);
                break;
        }
    }
}
  • Related