首页 > 解决方案 > 点击手势识别器不适用于 Xamarin 表单中的形状?

问题描述

我在 Xamarin Forms 中为 Shape 对象配备了 Tap Gesture Recognizer 以对点击事件做出反应,但是它不起作用。我尝试过使用 Path、Polygone 和 Polyline 对象。将形状包裹在框架中有效 - 但前提是我点击形状外部的区域。那不是我想要的。包装在 ContentView 中也没有效果。也许这都是因为形状在 XF 中仍处于试验阶段(您必须在 App 类中设置 Shapes_Experimental 标志才能使用形状)?

这是一个适用于盒子但不适用于三角形的简单示例,在 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
            };
        }
    }

有谁知道如何使手势与形状一起使用的解决方案或解决方法?

标签: eventsxamarin.formstouchshapesgesture

解决方案


这是 Polygon/Polyline 的 iOS 实现中的一个错误。

对于解决方法,将 包装Shape在另一个视图中并将其设置InputTransparentPolygontrue。当 Shape 在另一个元素中时,Shape 仍然在顶部并且仍然从用户那里获得点击,因此您必须将点击向下传递给包装容器,无论是 Frame 还是 ContentView。例如:

    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
    };

更新: 如果您只需要在点击实际三角形时点击工作,那么您将需要在特定于平台的渲染器中执行此操作,并使用 iOS/Android/UWP SDK API 进行命中测试。

由于 Xamarin.Forms Shape 是 View,而 View 是矩形,因此将 TapGestureRecognizer 添加到 Shape 将触发 View 框的 Tap,而不是其中的形状。当 Shape 未包含在 Frame 等中时,这就是在 Android 上发生的情况。

Xamarin 论坛上有关于在 Xamarin.Forms 中获取点击坐标的讨论:https ://forums.xamarin.com/discussion/17767/touch-coordinates-in-tapgesturerecognizer

有关在 Xamarin.iOS中处理触摸事件的文档: https : //docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/touch/ 有关在 Xamarin.Android 中处理触摸事件的文档:https://docs。 microsoft.com/en-us/xamarin/android/app-fundamentals/touch/touch-in-android 有关在 UWP 中处理触摸事件的文档:https ://docs.microsoft.com/en-us/windows/uwp/design /输入/触摸交互

或者,您可以将 SkiaSharp 用于您的形状:https ://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/transforms/touch

还有一个付费插件,在上面链接的 Xamarin 论坛讨论中指出(我不能保证),声称可以确定触摸发生的位置:https ://www.mrgestures.com/


推荐阅读