0

I have an MKMapView based app with a button bar, when a user selects an annotation on the mapview a button is available to display a popover from the button bar.

The popover only covers a portion of the map view what I want to be able to do is when the user scrolls the visible portion of the map view behind the popover I want the popover to fade to show the map view behind it, when the user stops scrolling I want the popover to fade in again after a second or so.

I understand I can define views I still want to be able to interact with while the popover is over but what is the best way to go about the fading?

Thanks, Mark

markab
  • 1

1 Answers1

1

To know when the user drags the map, you need a delegate on the MKMapView, and respond to regionWillChangeAnimated and regionDidChangeAnimated. The documentation claims that these may be called multiple times during a drag, but I don't see that happening.

However, see this discussion of these delegate methods not being called reliably.

Edit: my original answer suggested using Core Animation to fade the popover, but this isn't feasible. See the comments. Even if you get the popover's contentViewController, and get its view, and change that view's alpha, the popover leaves a shadow unless you go searching through the layer hierarchy. If at all possible, dismiss and present the popover instead. This may be less convenient than Core Animation, as you may need an NSTimer to control the delay before it is restored.

For other views on top of map views, once you know when dragging is happening, use Core Animation to fade your popover out and back in again. Adjust the durations, delays and name of the view to fade to suit.

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
{
    [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
    {
        [[self viewOnTopOfMapView] setAlpha:0.0];
    }
    completion:nil];
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
{
    [UIView animateWithDuration:0.25 delay:2.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
    {
         [[self viewOnTopOfMapView] setAlpha:1.0];
    }
    completion:nil];
}
Community
  • 1
  • 1
Cowirrie
  • 7,218
  • 1
  • 29
  • 42
  • I took a look at your code example however I don't think you can call setAlpha on a popover or am I getting something wrong? – markab Apr 09 '12 at 09:18
  • Oops, yes. You could access the `popoverController.contentViewController.view`, but making that transparent, or moving it, leaves a separate shadow behind. That shadow is created by a view a couple of levels up in the view hierarchy, with class `_UIPopoverView`, and the shadow is applied to the first sublayer of its main layer. Personally, I wouldn't mess with it. For your purposes, would it work to detect map movement as above and then dismiss the popover until the map movement ends? You might need a UITimer to delay the popover reappearrance, but that would be simple enough. – Cowirrie Apr 09 '12 at 11:04