18

I'm looking for a way to implement in iOS something that works as closely as possible to the Android Navigation Drawer.

That's basically a menu panel that slides in from the left and over the current view.

I've looked at using ECSlidingViewController, MMDrawerController, etc. but I'd really want a drawer that appears on top of the current view, not like the Facebook app where the current view slides to reveal a menu underneath.

How can I implement my desired functionality?

Community
  • 1
  • 1
Mirko N.
  • 10,537
  • 6
  • 38
  • 37
  • 1
    Probably going to have to roll your own. It's not particularly hard to do, tie a swipe gesture recognizer to a method that animates the new view's frame into position from off screen. – ryan cumley Oct 29 '13 at 16:57
  • 1
    Obviously It can be done, I have a working code but it's too huge to write here, If you're looking for outline I can provide? – ManicMonkOnMac Oct 29 '13 at 17:07
  • @ManicMonkOnMac some pointers would be great thanks – Mirko N. Oct 29 '13 at 17:09
  • Ok I am trying to write a succinct answer. – ManicMonkOnMac Oct 29 '13 at 17:38
  • I've tried my best to write a good answer but it was difficult, let me know if you face any issues. – ManicMonkOnMac Oct 29 '13 at 18:28
  • Question edited to remove the impression that it may simply be asking to "recommend or find a tool, library or favorite off-site resource" – Mirko N. Oct 30 '13 at 09:57
  • 4
    I'm so sick of StackOverflow closing questions all the time because some users find the questions `off-topic` or whatever, not all programmers are senior programmers, not all questions have to be advanced questions, and this question is not `off-topic` whatsoever. – Fadi Obaji May 01 '15 at 11:45
  • 2
    @FadiObaji resource requests are off-topic for [good reason](http://meta.stackoverflow.com/questions/267503/answering-off-topic-questions/267504#267504). –  May 01 '15 at 13:00
  • 2
    @Snowman this question is not off-topic, it's a real good question for ios beginners, and ios SDK does not provide `NavigationDrawer` like android does – Fadi Obaji May 01 '15 at 13:11
  • 5
    The reason this question was closed no longer applies (if it ever did). It is on topic, answerable, and both the question and the answer are highly rated. It should be reopened. – Darshan Rivka Whittle Jun 03 '15 at 16:52
  • @FadiObaji i wish there was down vote button on comments – vishal dharankar Dec 14 '16 at 10:59
  • @vishal well, there is not, get over it :) – Fadi Obaji Dec 15 '16 at 13:29
  • @FadiObaji and people take disadvantage of it :D – vishal dharankar Dec 15 '16 at 13:32

1 Answers1

17

You would need a SlideOverViewController that has a table view with width as much as you want to overlap, set the background color of the view as clear color(to achieve transparency).

in your MainViewController, initialize and add your SlideOverViewController.

    self.slideOverViewController = [[SlideOverViewController alloc] init];
    self.slideOverViewController.view.frame = CGRectMake(-self.myNavigationController.view.frame.size.width, 0, self.myNavigationController.view.frame.size.width, self.view.frame.size.height);
    self.slideOverViewController.delegate = self;

To activate your slideOverMenu use:

    [self.slideOverViewController.view setHidden:NO];

    [self.view addSubview:self.slideOverViewController.view];

    [UIView animateWithDuration:kMenuAnimationDuration animations:^{

    self.slideOverViewController.view.frame = CGRectMake(0, 0, self.slideOverViewController.view.frame.size.width, self.slideOverViewController.view.frame.size.height);

    [UIView animateWithDuration:kMenuAnimationDuration animations:^{


    }completion:^(BOOL finished){

    }];

}completion:^(BOOL finished){
    self.mainMenuDisplay = YES;
}];

To hide the menu use:

        [UIView animateWithDuration:kMenuAnimationDuration animations:^{

        self.slideOverViewController.view.frame = CGRectMake(-self.myNavigationController.view.frame.size.width - 80, 0, self.myNavigationController.view.frame.size.width, self.myNavigationController.view.frame.size.height);

    }completion:^(BOOL finished){

        self.mainMenuDisplay = NO;
        [self.slideOverViewController.view setHidden:YES];
    }];

In you SLideOverViewController,

add gestureRecognizers:

    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestures:)];
[panGesture setMinimumNumberOfTouches:1];
[panGesture setMaximumNumberOfTouches:1];



  - (void) handlePanGestures : (UIPanGestureRecognizer *) sender
{
if (self.view.frame.origin.x > 0) {
    return;
}

[self.view bringSubviewToFront:[(UIPanGestureRecognizer*)sender view]];
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];

if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
    self.firstX = [[sender view] center].x;
    self.firstY = [[sender view] center].y;
}

translatedPoint = CGPointMake(self.firstX+translatedPoint.x, self.firstY);

if (translatedPoint.x > self.view.frame.size.width/2) {
    self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    return;
}

[[sender view] setCenter:translatedPoint];

if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded || [sender state] == UIGestureRecognizerStateCancelled || [sender state] == UIGestureRecognizerStateFailed) {

    CGFloat velocityX = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].x);
    CGFloat finalX = translatedPoint.x + velocityX;
    CGFloat finalY = self.firstY;

    if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {
        if (finalX < 0) {
            //finalX = 0;
        } else if (finalX > 768) {
            //finalX = 768;
        }

        if (finalY < 0) {
            finalY = 0;
        } else if (finalY > 1024) {
            finalY = 1024;
        }
    } else {
        if (finalX < 0) {
            //finalX = 0;
        } else if (finalX > 1024) {
            //finalX = 768;
        }

        if (finalY < 0) {
            finalY = 0;
        } else if (finalY > 768) {
            finalY = 1024;
        }
    }

    CGFloat animationDuration = (ABS(velocityX)*.0002)+.2;

    [self animateToPoint:finalX yPos:finalY withAnimationDuration:animationDuration];
}
}
}
}

- (void) animateToPoint : (CGFloat) finalX yPos : (CGFloat) finalY withAnimationDuration : (CGFloat) animationDuration {
if (self.view.frame.origin.x < -90) {
    [self handleCloseSlidingMenuViewController];

} else {
    [self handleShowSlidingMenuView : finalX yPos:finalY withAnimationDuration:animationDuration];
}}

- (void) handleShowSlidingMenuView : (CGFloat) finalX
                          yPos : (CGFloat) finalY
         withAnimationDuration : (CGFloat) animationDuration{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidFinish)];
self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];}
ManicMonkOnMac
  • 1,476
  • 13
  • 21