Frank Zielen
Frank Zielen

Reputation: 137

Tap Gesture Recognizer not working with Shapes in Xamarin Forms?

I have equipped a Shape object in Xamarin Forms with a Tap Gesture Recognizer to react on tap events, however, it does not work. I have tried with Path, Polygone and Polyline objects. Wrapping the shape in a Frame works - but only if I tap on the area outside the shape. That's not what I want. Wrapping in a ContentView shows also no effect. Maybe that's all because shapes are still experimental in XF (you must set the Shapes_Experimental flag in the App class to use shapes)?

Here's a simple example working for the box but not for the triangle, tested on iOS:

public class TestPage : ContentPage
    {
        public TestPage()
        {
            var tgr = new TapGestureRecognizer();
            tgr.Tapped += async (s, e) => {
                await DisplayAlert("Info", "Tapped", "OK");
            };

            Polygon triangle = new Polygon
            {
                Points = new PointCollection(),
                Fill = Brush.Blue,
            };
            triangle.Points.Add(new Point(0, 0));
            triangle.Points.Add(new Point(100, 0));
            triangle.Points.Add(new Point(50, 50));

            triangle.GestureRecognizers.Add(tgr);

            BoxView box = new BoxView
            {
                HeightRequest = 50,
                Color = Color.Red
            };

            box.GestureRecognizers.Add(tgr);

            Content = new StackLayout
            {
                Children = { triangle, box },
                HorizontalOptions = LayoutOptions.Center,
                VerticalOptions = LayoutOptions.Center
            };
        }
    }

Does anyone knows a solution or workaround how to make gestures work with shapes?

Upvotes: 0

Views: 1334

Answers (2)

jgoldberger - MSFT
jgoldberger - MSFT

Reputation: 6088

This is a bug on the iOS implementation of Polygon/Polyline.

For a workaround, wrap the Shape in another view and set InputTransparent on the Polygon to true. When the Shape is in another element, the Shape is still on top and still gets the tap from the user, so you have to pass the tap down to the wrapping container, whether a Frame or ContentView. E.g.:

    var tgr = new TapGestureRecognizer();
    tgr.Tapped += async (s, e) => {
        await DisplayAlert("Info", "Tapped", "OK");
    };

    Polygon triangle = new Polygon
    {
        Points = new PointCollection(),
        Fill = Brush.Blue,
    };
    triangle.Points.Add(new Point(0, 0));
    triangle.Points.Add(new Point(100, 0));
    triangle.Points.Add(new Point(50, 50));
    triangle.InputTransparent = true;  // <------------------------set InputTransparent to True

    var frame= new Frame(); 
    frame.Content = triangle; // <--------------------- add to Frame
 
    frame.GestureRecognizers.Add(tgr); // <-----------TapGestureRecognizer on Frame

    Content = new StackLayout
    {
        Children = { frame }, // <------------------------ add Frame to view heirarchy
        HorizontalOptions = LayoutOptions.Center,
        VerticalOptions = LayoutOptions.Center
    };

UPDATE: If you need to only have the tap work when the actual triangle is being tapped, then you will need to do that in platform specific renderers and use the iOS/Android/UWP SDK APIs to do hit tests.

Since a Xamarin.Forms Shape is a View, and a View is rectangular, adding a TapGestureRecognizer to a Shape will trigger the Tap for the View box, not for the shape inside of it. This is what happens on Android when the Shape is not wrapped in a Frame, etc.

There is a discussion of getting the tap coordinates in Xamarin.Forms on the Xamarin Forums: https://forums.xamarin.com/discussion/17767/touch-coordinates-in-tapgesturerecognizer

Docs on handling touch events in Xamarin.iOS: https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/touch/ Docs on handling touch events in Xamarin.Android: https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/touch/touch-in-android Docs on handling touch events in UWP: https://learn.microsoft.com/en-us/windows/uwp/design/input/touch-interactions

Alternately you could use SkiaSharp for your shapes: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/transforms/touch

And there is a paid plugin, noted in the Xamarin Forums discussion linked above (I can't vouch for it) that claims to enable determining where the touch occurred: https://www.mrgestures.com/

Upvotes: 2

Daniel Klauser
Daniel Klauser

Reputation: 454

Why dont you wrap a Frame around your Triangle and add the TabGestureRecognizer there?

Upvotes: 0

Related Questions