带有覆盖视图的iOS MKMapView捕捉选定的触摸/手势

时间:2015-03-25 12:50:57

标签: ios xamarin uiview touch mkmapview

我尝试使用覆盖视图实现MKMapView,绘制可编辑的多边形。因此,我需要有选择地捕捉目标顶点的触摸手势,但让其他触摸/手势通过滚动和缩放地图。

那么我如何以编程方式将所选的触摸发送到地图或叠加层,具体取决于它们的坐标?

以下代码简化为简化场景:叠加视图左侧为红色,右侧为蓝色。一方应抓住触摸事件,另一方应允许地图交互。

地图和叠加层都是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);
    }
}

结果屏幕如下所示:

enter image description here

当触摸红色部分时,我希望与地图互动 - 这不起作用。 当触摸蓝色部分时,我想看到手势识别器的控制台输出 - 这确实有效。

什么行不通:

  • 将叠加层调整为仅一半的屏幕。

    在这个人为的例子中,这会有所帮助。但在我的现实应用中,触摸与无触摸之间的区别更为复杂。

  • 将手势检测器添加到MapView

    each gesture recognizer will receive touch events in a non-deterministic order开始,您永远不知道地图或手势检测器是否首先接收到触摸事件。因此,即使触摸不应该已经收到地图,地图也可能已经滚动。

  • 覆盖HitTestPointInside

    我尝试在SuperViewMapView和/或Overlay中覆盖这些方法。但它们要么没有被召唤,要么似乎没有效果。至少我可以阻止手势识别器接收红色区域上的触摸。但它并没有像预期的那样到达地图。也许我做错了什么。但似乎地图忽略了转发的触摸。

1 个答案:

答案 0 :(得分:0)

我似乎已经解决了上述问题。显然,MKMapView不应该是子视图,但需要成为View的{​​{1}}:

ViewController

然后public sealed class SuperView: UIViewController { readonly UIView map = new MKMapView(); readonly UIView overlay = new Overlay(); public SuperView() { View = map; map.AddSubview(overlay); } } 视图获得Overlay实现:

HitTest