Search code examples
c#event-handlingmauidouble-click

Maui: different events for single and double tapped


How do I create different methods when double-tap vs. single-tap? How to recreate:

  1. Take the default "New Maui App"
  2. Add the first two code blocks from this documentation: https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/gestures/tap?view=net-maui-7.0
  3. Then add a second function for single-tap The MainPage.Xaml now looks like this (truncated after image part since the rest is the same):
<?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"
             x:Class="MauiApp2.MainPage">

    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" >
                <!--******* add gesture recognizers to default app ******-->
                <Image.GestureRecognizers>
                    <TapGestureRecognizer Tapped="OnTapGestureRecognizerDoubleTapped"
                              NumberOfTapsRequired="2" />
                    <TapGestureRecognizer Tapped="OnTapGestureRecognizerSingleTapped"
                              NumberOfTapsRequired="1" />
                </Image.GestureRecognizers>
                <!--******** end add gesture recognizers to default app *******-->
            </Image>

            <Label
                Text="Hello, World!"
...

Then in MainPage.xaml.cs, I've added the two methods:

    void OnTapGestureRecognizerDoubleTapped(object sender, TappedEventArgs args)
    {
        CounterBtn.Text = $"Double tapped image";

    }
    void OnTapGestureRecognizerSingleTapped(object sender, TappedEventArgs args)
    {
        CounterBtn.Text = $"Single tapped image";

    }

Now, when you run and double-click/tap the image, it goes first to the single-tap method, then the double-tap method, then back to the single-tap method.

What is the best way to prevent calls to the single-tap method?


Solution

  • based on these comments, I implemented the double-tap vs single-tap like this:

        bool doubleTapped;
        bool ignoreNextTap;
        void OnTapGestureRecognizerDoubleTapped(object sender, TappedEventArgs args)
        {
            doubleTapped = true;
        }
        async void OnTapGestureRecognizerSingleTapped(object sender, TappedEventArgs args)
        {
            var delay = Task.Delay(555);
            await delay;
            if (ignoreNextTap)
            {
                ignoreNextTap = false;
                return;
            }
            if (doubleTapped)
            {
                doubleTapped = false;
                ignoreNextTap = true;
                CounterBtn.Text = $"Double tapped image";
            }
            else
            {
                CounterBtn.Text = $"Single tapped image";
            }
        }
    

    It works, but it sure seems hacky. Basically, what single tap method sleeps for half-of-a-second, to see if the doubleTapped flag will be raised. If it is, then it calls the code that should be executed for doubleTap ("CounterBtn.Text = $"Double tapped image";"). Otherwise, it calls the singleTap code ("CounterBtn.Text = $"Single tapped image";"). However, in order to prevent the second single click from registering, I put another Boolean for ignoreNextTap. I saw similar posts from other languages (How to customize singleclick to doubleclick? js) and the general approach is the same as this. I guess there is no other way to do this other than the Delay/Sleep approach to see if a second click happens. This will generally cut into the snappy-ness of the UI.