Wenn Sie nur die Karte Blick auf die Overlay einfrieren möchten, können Sie den angezeigten Kartenausschnitt der Region auf die Grenzen des Overlays festgelegt und eingestellt scrollEnabled
und zoomEnabled
-NO
.
Aber das lässt den Benutzer nicht innerhalb der Grenzen des Overlays scrollen oder zoomen.
Es gibt keine integrierten Möglichkeiten, die Kartenansicht auf die Grenzen des Overlays zu beschränken. Sie müssten dies also manuell tun. Stellen Sie zunächst sicher, dass Ihr Objekt MKOverlay
die Eigenschaft boundingMapRect
implementiert. Dies kann dann in der Delegatenmethode regionDidChangeAnimated
verwendet werden, um die Ansicht nach Bedarf manuell anzupassen.
Hier ist ein Beispiel, wie dies getan werden könnte.
Code unten sollte in der Klasse sein, die die MKMapView
hat.
Stellen Sie sicher, dass die Kartenansicht anfänglich auf eine Region eingestellt ist, in der das Overlay sichtbar ist.
//add two ivars to the .h...
MKMapRect lastGoodMapRect;
BOOL manuallyChangingMapRect;
//in the .m...
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect)
return;
lastGoodMapRect = mapView.visibleMapRect;
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect) //prevents possible infinite recursion when we call setVisibleMapRect below
return;
// "theOverlay" below is a reference to your MKOverlay object.
// It could be an ivar or obtained from mapView.overlays array.
BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);
if (mapContainsOverlay)
{
// The overlay is entirely inside the map view but adjust if user is zoomed out too much...
double widthRatio = theOverlay.boundingMapRect.size.width/mapView.visibleMapRect.size.width;
double heightRatio = theOverlay.boundingMapRect.size.height/mapView.visibleMapRect.size.height;
if ((widthRatio < 0.6) || (heightRatio < 0.6)) //adjust ratios as needed
{
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
manuallyChangingMapRect = NO;
}
}
else
if (![theOverlay intersectsMapRect:mapView.visibleMapRect])
{
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
}
}
Ich habe versucht, dies mit dem eingebauten in MKCircle
Overlay und scheint gut zu funktionieren.
EDIT:
Es ist gut 95% der Zeit funktioniert, aber ich habe durch einige Tests bestätigt, dass es zwischen zwei Standorten, dann geben Sie eine Endlosschleife schwingen könnte. Also, ich bearbeiten ihm ein bisschen, ich denke, das das Problem lösen soll:
// You can safely delete this method:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
// prevents possible infinite recursion when we call setVisibleMapRect below
if (manuallyChangingMapRect) {
return;
}
// "theOverlay" below is a reference to your MKOverlay object.
// It could be an ivar or obtained from mapView.overlays array.
BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);
if (mapContainsOverlay) {
// The overlay is entirely inside the map view but adjust if user is zoomed out too much...
double widthRatio = theOverlay.boundingMapRect.size.width/mapView.visibleMapRect.size.width;
double heightRatio = theOverlay.boundingMapRect.size.height/mapView.visibleMapRect.size.height;
// adjust ratios as needed
if ((widthRatio < 0.6) || (heightRatio < 0.6)) {
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
manuallyChangingMapRect = NO;
}
} else if (![theOverlay intersectsMapRect:mapView.visibleMapRect]) {
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
manuallyChangingMapRect = NO;
} else {
lastGoodMapRect = mapView.visibleMapRect;
}
}
Und für den Fall, dass jemand für eine schnelle MKOverlay
Lösung sucht, ist hier ein:
- (void)viewDidLoad {
[super viewDidLoad];
MKCircle* circleOverlay = [MKCircle circleWithMapRect:istanbulRect];
[_mapView addOverlay:circleOverlay];
theOverlay = circleOverlay;
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
MKCircleView* circleOverlay = [[MKCircleView alloc] initWithCircle:overlay];
[circleOverlay setStrokeColor:[UIColor mainColor]];
[circleOverlay setLineWidth:4.f];
return circleOverlay;
}
Vielen Dank! Das hat den Trick gemacht. – mag725
hat ganz gut funktioniert. behandelt keine Fälle, in denen Sie die Ansicht außerhalb Ihrer Grenzen schwenken (scrollen, scrollen, was auch immer). – horseshoe7
@ horseshoe7, springt die Ansicht in das Overlay zurück, nachdem Sie die Geste beendet haben? Außerdem muss die Karte innerhalb des Overlays beginnen, damit das obige funktioniert.Wenn Sie _while_ einschränken müssen, während der Benutzer die Karte verschiebt, können Sie _might_ dies mit einem UIPanGestureRecognizer tun und den neuen Kartenbereich im Gestenhandler überprüfen. – Anna