Si sólo desea congelar la vista del mapa en la superposición, podría configurar región de la vista del mapa a los límites de la superposición y establecer scrollEnabled
y zoomEnabled
a NO
.
Pero eso no permitirá al usuario desplazarse o acercarse dentro de los límites de la superposición.
No hay formas integradas de restringir la vista del mapa a los límites de la superposición, por lo que tendría que hacerlo manualmente. Primero, asegúrese de que su objeto MKOverlay
implemente la propiedad boundingMapRect
. Esto se puede usar en el método de delegado regionDidChangeAnimated
para ajustar manualmente la vista según sea necesario.
Aquí hay un ejemplo de cómo se podría hacer esto.
El siguiente código debe estar en la clase que tiene el MKMapView
.
Asegúrate de que la vista del mapa esté inicialmente configurada en una región donde la superposición esté visible.
//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];
}
}
He intentado esto con la incorporada en el MKCircle
superposición y parece funcionar bien.
EDIT:
No funciona bien el 95% de las veces, sin embargo, he confirmado a través de algunas pruebas de que podría oscilar entre dos ubicaciones, a continuación, entrar en un bucle infinito. Por lo tanto, he editado un poco, creo que esto debería resolver el problema:
// 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;
}
}
Y en caso de que alguien está buscando una solución rápida MKOverlay
, aquí es una:
- (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;
}
¡Gracias! Eso hizo el truco. – mag725
funcionó bastante bien. no maneja los casos en los que desplaza (desplaza, desplaza, desplaza, lo que sea) la vista fuera de sus límites, sin embargo. – horseshoe7
@ horseshoe7, ¿vuelve la vista a la superposición después de finalizar el gesto? Además, el mapa debe comenzar dentro de la superposición para que funcione lo anterior.Si necesita restringir _while_ el usuario está moviendo el mapa, _might_ podrá hacerlo usando un UIPanGestureRecognizer y verificando la nueva región del mapa en el controlador de gestos. – Anna