我尝试使用覆盖视图实现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);
}
}
结果屏幕如下所示:
当触摸红色部分时,我希望与地图互动 - 这不起作用。 当触摸蓝色部分时,我想看到手势识别器的控制台输出 - 这确实有效。
什么行不通:
将叠加层调整为仅一半的屏幕。
在这个人为的例子中,这会有所帮助。但在我的现实应用中,触摸与无触摸之间的区别更为复杂。
将手势检测器添加到MapView
。
从each gesture recognizer will receive touch events in a non-deterministic order开始,您永远不知道地图或手势检测器是否首先接收到触摸事件。因此,即使触摸不应该已经收到地图,地图也可能已经滚动。
覆盖HitTest
或PointInside
。
我尝试在SuperView
,MapView
和/或Overlay
中覆盖这些方法。但它们要么没有被召唤,要么似乎没有效果。至少我可以阻止手势识别器接收红色区域上的触摸。但它并没有像预期的那样到达地图。也许我做错了什么。但似乎地图忽略了转发的触摸。
答案 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