How to limit a mapview to a defined envelop?

2473
5
09-06-2010 09:54 AM
MelvinTan
New Contributor
Is it possible to limit the map view to a defined envelop so that the map cannot be panned beyond the envelop?
0 Kudos
5 Replies
NimeshJarecha
Esri Regular Contributor
No, unfortunately it is not possible to limit the boundary of map view.

Regards,
Nimesh
0 Kudos
KOLDODUARTE
New Contributor
No, unfortunately it is not possible to limit the boundary of map view.

Regards,
Nimesh


Do you think that this feature or property will be implemented in the API on a final version? Because when I do zoom out on a mapView without custom envelop, the white background sees and it is some ugly.

BR,
Koldo.
0 Kudos
DanaMaher
Occasional Contributor
Is it possible to limit the map view to a defined envelop so that the map cannot be panned beyond the envelop?


You can home brew this functionality easily and I am using it successfully for several things I'm working on. You simply need to spin off a new thread that constantly polls the map view's current envelope to determine whether the user has zoomed out further than you like.

Although you should of course keep the number of threads running to an absolute minimum, the extent patrolling thread is not a resource hog and this is the only way to do it until ESRI implements this function within the SDK where it can run on one of their background threads.

Below is the basic code for doing this. You would presumably call startPatrollingExtent in viewDidLoad or when you want to start limiting user movement. Changing the value of the patrolling instance of the stateTrooper typedef will kill the thread and you can then reinitialize it by calling startPatrollingExtent again.

You should also prevent the user from being able to interact with the map while it is reframing so that multiple zoomToEnvelope calls are not sent, although I have not seen that cause problems or crashes. Also, setting up a few cases where the map reframes according to how the user gets out of bounds makes the reframing look a lot better. For instance, if the user does a pinch zoom and pulls out too wide, it makes sense to simply zoom back to the maximum extent. If, however, the user is zoomed in very close and drags outside of the allowed envelope, it makes more sense to pull them back to the edge than it does to zoom to the full allowed extent.
  
Make sure and read up on threading first if you are unfamiliar.

-(void)startPatrollingExtent; //begin limiting the extent to which the user can zoom
{
stateTrooper = patrolling;
[NSThread detachNewThreadSelector:@selector(startPatrollingExtentThread) toTarget:self withObject:nil];
}

-(void)startPatrollingExtentThread;
{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (stateTrooper == patrolling)
{
  [self performSelectorOnMainThread:@selector(checkExtent) withObject:nil waitUntilDone:YES]; 
}
[pool drain];
}

-(void)checkExtent;
{
if (framer == areNotReframing) //if we are currently reframing, do nothing
{
  if([patrolledExtent containsEnvelope:theImageMap.envelope]) //if we are still inside the patrolled extent, no biggie
  {
  
  }
  else { //zoom back to patrolled extent
   [theImageMap zoomToEnvelope:patrolledExtent animated:YES];
  }
 
}
}
0 Kudos
KOLDODUARTE
New Contributor
Hi Bernese,

This evening, I will try it.

Thank you for your report!!
0 Kudos
DanaMaher
Occasional Contributor
A quick update; I found that it is better to run the checking method on a timer rather than a while loop since the number of calls per unit time performed by the while loop is simply excessive. The startPatrollingExtent method looks like this with a timer:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(checkExtent) userInfo:nil repeats:YES];

while (stateTrooper == patrolling)
{
  [[NSRunLoop currentRunLoop] run]; 
}

[pool drain];
0 Kudos