iOS MKMapView 覆盖视图捕捉已选中touches/gestures

iOS MKMapView with overlay view catching selected touches/gestures

我正在尝试实现一个带有叠加视图的 MKMapView,它绘制一个可编辑的多边形。因此,我需要有选择地捕捉针对顶点的触摸手势,但让其他 touches/gestures 允许滚动和缩放地图。

那么我如何根据坐标以编程方式将选定的触摸发送到地图或叠加层?

以下代码将其归结为一个简化的场景:叠加视图在左侧为红色,在右侧为蓝色。一侧应捕获触摸事件,另一侧应允许地图交互。

map 和 overlay 都是 SuperView:

上的子视图
public sealed class SuperView: UIView
{
    readonly UIView map = new MapView();
    readonly UIView overlay = new Overlay();

    public SuperView()
    {
        AddSubview(map);
        AddSubview(overlay);
    }

    public override UIView HitTest(CGPoint point, UIEvent uievent)
    {
        return point.X < Frame.Width / 2 ? map : overlay;
    }
}

MapView 派生自 MKMapView 并且只确保允许滚动:

public sealed class MapView: MKMapView
{
    public MapView() : base(UIScreen.MainScreen.Bounds)
    {
        ScrollEnabled = true;
    }
}

Overlay 包含手势识别器并可视化两个区域:

public sealed class Overlay: UIView
{
    public Overlay() : base(UIScreen.MainScreen.Bounds)
    {
        BackgroundColor = new UIColor(0, 0, 0, 0);
        AddGestureRecognizer(new Recognizer());
    }

    public override void Draw(CGRect rect)
    {
        using (var context = UIGraphics.GetCurrentContext()) {
            context.SetFillColor(new CGColor(1, 0, 0, 0.25f));
            context.FillRect(new CGRect(rect.Left, rect.Top, rect.Width / 2, rect.Height));
            context.SetFillColor(new CGColor(0, 0, 1, 0.25f));
            context.FillRect(new CGRect(rect.Width / 2, rect.Top, rect.Width / 2, rect.Height));
        }
    }
}

识别器很直接:

public sealed class Recognizer: UIGestureRecognizer
{
    public override void TouchesBegan(NSSet touches, UIEvent evt)
    {
        Console.WriteLine("TouchesBegan");
        base.TouchesBegan(touches, evt);
    }

    public override void TouchesMoved(NSSet touches, UIEvent evt)
    {
        Console.WriteLine("TouchesMoved");
        base.TouchesMoved(touches, evt);
    }

    public override void TouchesEnded(NSSet touches, UIEvent evt)
    {
        Console.WriteLine("TouchesEnded");
        base.TouchesEnded(touches, evt);
    }

    public override void TouchesCancelled(NSSet touches, UIEvent evt)
    {
        Console.WriteLine("TouchesCancelled");
        base.TouchesCancelled(touches, evt);
    }
}

生成的屏幕如下所示:

当触摸红色部分时,我希望与地图进行交互 - 但这是行不通的。 触摸蓝色部分时,我想查看手势识别器的控制台输出 - 这确实有效。

什么不起作用:

我好像已经解决了上面描述的问题。显然,MKMapView 不应该是子视图,而需要是 ViewControllerView:

public sealed class SuperView: UIViewController
{
    readonly UIView map = new MKMapView();
    readonly UIView overlay = new Overlay();

    public SuperView()
    {
        View = map;
        map.AddSubview(overlay);
    }
}

然后 Overlay 视图获得 HitTest 实现:

    public override UIView HitTest(CGPoint point, UIEvent uievent)
    {
        return point.X < Frame.Width / 2 ? null : base.HitTest(point, uievent);
    }