kenken
kenken

Reputation: 25

Show half sreen view that slides down from the top

I have a mapView which has a size of (320, 182). Once the UIBarButtonItem is pressed, I would like to show this mapView sliding down from top of the screen. To achieve this, I have written a code like this.

    UIBarButtonItem *mapButton = [[UIBarButtonItem alloc]
                              initWithImage:[UIImage imageNamed:@"map_1.png"]
                              style:UIBarButtonItemStylePlain
                              target:self
                              action:@selector(showMap:)
                              ];
    self.navigationItem.rightBarButtonItem = mapButton;


    -(void)showMap:(id)sender{
        self._mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,-182,320,182)];
        [self.scrollView addSubview:self._mapView];

        //show view
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:1.0];
        CGRect rect = [self._mapView frame];
        rect.origin.y = 0;
        [self._mapView setFrame:rect];
        [UIView commitAnimations];
    }

This will show the map view which slides down from top of the screen. However, how do I make the mapView dismiss when the UIBarButtonItem been pressed on the second time? Moreover, I also would like to dismiss the mapView when tapped outside the mapView.

Upvotes: 0

Views: 511

Answers (2)

Matt
Matt

Reputation: 2359

This is a vary basic implementation of what you are asking for. But it will do the trick.

#import "ViewController.h"
#import "MKMapView.h"

@interface ViewController () {
    MKMapView *mapView;
    BOOL showingMap;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //
    UIBarButtonItem *mapButton = [[UIBarButtonItem alloc]
                                  initWithTitle:@"Map"
                                  style:UIBarButtonItemStylePlain
                                  target:self
                                  action:@selector(toggleMap:)
                                  ];
    self.navigationItem.rightBarButtonItem = mapButton;

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissView:)];
    [self.view addGestureRecognizer:tapRecognizer];
}

-(void)toggleMap:(id)sender{
    if (!mapView) {
        mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,-182,320,182)];
        mapView.backgroundColor = [UIColor redColor];   // red background for testing
        [self.view addSubview:mapView];
    }

    CGRect rect = mapView.frame;
    rect.origin.y = showingMap ? -rect.size.height : 0;

    showingMap = !showingMap;

    [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        mapView.frame = rect;
    } completion:^(BOOL finished) {

    }];
}

- (void)dismissView:(UITapGestureRecognizer*)recognizer {
    // bail out since map isn't showing
    if (!showingMap) return;

    CGPoint pt = [recognizer locationInView:self.view];
    UIView *v = [self.view hitTest:pt withEvent:nil];

    if (![v isKindOfClass:[MKMapView class]]) {
        NSLog(@"dismiss");
        [self toggleMap:nil];
        return;
    }
}

@end

Upvotes: 2

Mundi
Mundi

Reputation: 80265

Just reverse the animation (which you should do in the more modern block methods):

rect.origin.y = -182; 
[UIView animateWithDuration:1.0 animations^{
    self.mapView.frame = rect;
}

Upvotes: 0

Related Questions