我試圖用覆蓋視圖實現一個MKMapView,該視圖繪製了一個可編輯的多邊形。因此,我需要選擇性地捕捉針對頂點的觸摸手勢,但通過其他觸摸/手勢來允許滾動和縮放地圖。帶有覆蓋視圖的iOS 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
。但是他們要麼沒有被調用,要麼似乎沒有效果。至少我可以阻止手勢識別器在紅色區域接收觸摸。但它沒有按預期到達地圖。也許我做錯了什麼。但看起來地圖忽略了轉發。