Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tap gesture recognizer secondary button mask #963

Merged
merged 6 commits into from
Oct 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 117 additions & 4 deletions docs/fundamentals/gestures/tap.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,46 @@
---
title: "Recognize a tap gesture"
description: "This article explains how to recognize a tap gesture in a .NET MAUI app."
ms.date: 02/23/2022
ms.date: 10/03/2022
---

# Recognize a tap gesture

A .NET Multi-platform App UI (.NET MAUI) tap gesture recognizer is used for tap detection and is implemented with the `TapGestureRecognizer` class. This class defines the following properties:

::: moniker range="=net-maui-6.0"

- `Command`, of type `ICommand`, which is executed when a tap is recognized.
- `CommandParameter`, of type `object`, which is the parameter that's passed to the `Command`.
- `NumberOfTapsRequired`, of type `int`, which represents the number of taps required to recognize a tap gesture. The default value of this property is 1.

::: moniker-end

::: moniker range=">=net-maui-7.0"

- `Buttons`, of type `ButtonsMask`, which defines whether the primary or secondary mouse button, or both, triggers the gesture on Mac Catalyst and Windows. For more information, see [Define the button masks](#define-the-button-mask).
- `Command`, of type `ICommand`, which is executed when a tap is recognized.
- `CommandParameter`, of type `object`, which is the parameter that's passed to the `Command`.
- `NumberOfTapsRequired`, of type `int`, which represents the number of taps required to recognize a tap gesture. The default value of this property is 1.

::: moniker-end

These properties are backed by `BindableProperty` objects, which means that they can be targets of data bindings, and styled.

::: moniker range="=net-maui-6.0"
The `TapGestureRecognizer` class also defines a `Tapped` event that's raised when a tap is recognized. The `TappedEventArgs` object that accompanies the `Tapped` event defines a `Parameter` property of type `object` that indicates the value passed by the `CommandParameter` property, if defined.
::: moniker-end

::: moniker range=">=net-maui-7.0"
The `TapGestureRecognizer` class also defines a `Tapped` event that's raised when a tap is recognized. The `TappedEventArgs` object that accompanies the `Tapped` event defines a `Parameter` property of type `object` that indicates the value passed by the `CommandParameter` property, if defined. The `TappedEventArgs` object also defines a `Buttons` property, and a `GetPosition` method. The `Buttons` property is of type `ButtonsMask`, and can be used to determine whether the primary or secondary mouse button triggered the gesture recognizer on Mac Catalyst and Windows. The `GetPosition` method returns a `Point?` object that represents the position at which the tap gesture was detected. For more information about button masks, see [Define the button mask](#define-the-button-mask). For more information about the `GetPosition` method, see [Get the gesture position](#get-the-gesture-position).
::: moniker-end

## Create a TapGestureRecognizer

To make a `View` recognize a tap gesture, create a `TapGestureRecognizer` object, handle the `Tapped` event, and add the new gesture recognizer to the `GestureRecognizers` collection on the view. The following code example shows a `TapGestureRecognizer` attached to an `Image`:

```xaml
<Image Source="tapped.jpg">
<Image Source="dotnet_bot.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="2" />
Expand All @@ -32,7 +51,7 @@ To make a `View` recognize a tap gesture, create a `TapGestureRecognizer` object
The code for the `OnTapGestureRecognizerTapped` event handler should be added to the code-behind file:

```csharp
void OnTapGestureRecognizerTapped(object sender, EventArgs args)
void OnTapGestureRecognizerTapped(object sender, TappedEventArgs args)
{
// Handle the tap
}
Expand All @@ -46,7 +65,101 @@ tapGestureRecognizer.Tapped += (s, e) =>
{
// Handle the tap
};
Image image = new Image();
image.GestureRecognizers.Add(tapGestureRecognizer);
```

By default the `Image` will respond to single taps. When the `NumberOfTapsRequired` property is set above one, the event handler will only be executed if the taps occur within a set period of time. If the second (or subsequent) taps don't occur within that period, they're effectively ignored.
By default the `Image` will respond to single taps. When the `NumberOfTapsRequired` property is set to greater than one, the event handler will only be executed if the taps occur within a set period of time. If the second (or subsequent) taps don't occur within that period, they're effectively ignored.

::: moniker range=">=net-maui-7.0"

## Define the button mask

A `TapGestureRecognizer` object has a `Buttons` property, of type `ButtonsMask`, that defines whether the primary or secondary mouse button, or both, triggers the gesture on Mac Catalyst and Windows. The `ButtonsMask` enumeration defines the following members:

- `Primary` represents the primary mouse button, which is typically the left mouse button.
- `Secondary` represents the secondary mouse button, which is typically the right mouse button.

The following example shows a `TapGestureRecognizer` that detects taps with the secondary mouse button:

```xaml
<Image Source="dotnet_bot.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped"
Buttons="Secondary" />
</Image.GestureRecognizers>
</Image>
```

The event handler for the `Tapped` event can determine which button triggered the gesture:

```csharp
void OnTapGestureRecognizerTapped(object sender, TappedEventArgs args)
{
// Handle the tap
if (args.Buttons == ButtonsMask.Secondary)
{
// Do something
}
}
```

The equivalent C# code is:

```csharp
TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer
{
Buttons = ButtonsMask.Secondary
};
tapGestureRecognizer.Tapped += (s, e) =>
{
// Handle the tap
if (args.Buttons == ButtonsMask.Secondary)
{
// Do something
}
};
Image image = new Image();
image.GestureRecognizers.Add(tapGestureRecognizer);
```

> [!WARNING]
> On Windows, a `TapGestureRecognizer` that sets the `Buttons` property to `Secondary` doesn't respect the `NumberOfTapsRequired` property when it's greater than one.

In addition, a `TapGestureRecognizer` can be defined so that either the primary or secondary mouse button triggers the gesture:

```xaml
<TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped"
Buttons="Primary,Secondary" />
```

The equivalent C# code is:

```csharp
TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer
{
Buttons = ButtonsMask.Primary | ButtonsMask.Secondary
};
```

## Get the gesture position

The position at which a tap gesture occurred can be obtained by calling the `GetPosition` method on a `TappedEventArgs` object. The `GetPosition` method accepts an `Element?` argument, and returns a position as a `Point?` object:

```csharp
void OnTapGestureRecognizerTapped(object sender, TappedEventArgs e)
{
// Position inside window
Point? windowPosition = e.GetPosition(null);

// Position relative to an Image
Point? relativeToImagePosition = e.GetPosition(image);

// Position relative to the container view
Point? relativeToContainerPosition = e.GetPosition((View)sender);
}
```

The `Element?` argument defines the element the position should be obtained relative to. Supplying a `null` value as this argument means that the `GetPosition` method returns a `Point?` object that defines the position of the tap gesture inside the window.

::: moniker-end