diff --git a/MMDrawerController/MMDrawerController.m b/MMDrawerController/MMDrawerController.m index 4aec238b..68b6edea 100644 --- a/MMDrawerController/MMDrawerController.m +++ b/MMDrawerController/MMDrawerController.m @@ -53,26 +53,26 @@ typedef void (^MMDrawerGestureCompletionBlock)(MMDrawerController * drawerController, UIGestureRecognizer * gesture); static CAKeyframeAnimation * bounceKeyFrameAnimationForDistanceOnView(CGFloat distance, UIView * view) { - CGFloat factors[32] = {0, 32, 60, 83, 100, 114, 124, 128, 128, 124, 114, 100, 83, 60, 32, - 0, 24, 42, 54, 62, 64, 62, 54, 42, 24, 0, 18, 28, 32, 28, 18, 0}; + CGFloat factors[32] = {0, 32, 60, 83, 100, 114, 124, 128, 128, 124, 114, 100, 83, 60, 32, + 0, 24, 42, 54, 62, 64, 62, 54, 42, 24, 0, 18, 28, 32, 28, 18, 0}; - NSMutableArray *values = [NSMutableArray array]; + NSMutableArray *values = [NSMutableArray array]; - for (int i=0; i<32; i++) - { - CGFloat positionOffset = factors[i]/128.0f * distance + CGRectGetMidX(view.bounds); - [values addObject:@(positionOffset)]; - } + for (int i=0; i<32; i++) + { + CGFloat positionOffset = factors[i]/128.0f * distance + CGRectGetMidX(view.bounds); + [values addObject:@(positionOffset)]; + } - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"]; - animation.repeatCount = 1; - animation.duration = .8; - animation.fillMode = kCAFillModeForwards; - animation.values = values; - animation.removedOnCompletion = YES; - animation.autoreverses = NO; + CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"]; + animation.repeatCount = 1; + animation.duration = .8; + animation.fillMode = kCAFillModeForwards; + animation.values = values; + animation.removedOnCompletion = YES; + animation.autoreverses = NO; - return animation; + return animation; } static NSString *MMDrawerLeftDrawerKey = @"MMDrawerLeftDrawer"; @@ -94,7 +94,7 @@ -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ UINavigationBar * navBar = [self navigationBarContainedWithinSubviewsOfView:self]; CGRect navBarFrame = [navBar convertRect:navBar.bounds toView:self]; if((self.centerInteractionMode == MMDrawerOpenCenterInteractionModeNavigationBarOnly && - CGRectContainsPoint(navBarFrame, point) == NO) || + CGRectContainsPoint(navBarFrame, point) == NO) || self.centerInteractionMode == MMDrawerOpenCenterInteractionModeNone){ hitView = nil; } @@ -145,19 +145,19 @@ @implementation MMDrawerController #pragma mark - Init - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - if (self) { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { [self commonSetup]; - } - return self; + } + return self; } - (id)initWithCoder:(NSCoder *)aDecoder{ - self = [super initWithCoder:aDecoder]; - if (self) { + self = [super initWithCoder:aDecoder]; + if (self) { [self commonSetup]; - } - return self; + } + return self; } -(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController{ @@ -211,36 +211,36 @@ - (void)encodeRestorableStateWithCoder:(NSCoder *)coder{ if (self.leftDrawerViewController){ [coder encodeObject:self.leftDrawerViewController forKey:MMDrawerLeftDrawerKey]; } - + if (self.rightDrawerViewController){ [coder encodeObject:self.rightDrawerViewController forKey:MMDrawerRightDrawerKey]; } - + if (self.centerViewController){ [coder encodeObject:self.centerViewController forKey:MMDrawerCenterKey]; } - + [coder encodeInteger:self.openSide forKey:MMDrawerOpenSideKey]; } - (void)decodeRestorableStateWithCoder:(NSCoder *)coder{ UIViewController *controller; MMDrawerSide openside; - + [super decodeRestorableStateWithCoder:coder]; if ((controller = [coder decodeObjectForKey:MMDrawerLeftDrawerKey])){ self.leftDrawerViewController = controller; } - + if ((controller = [coder decodeObjectForKey:MMDrawerRightDrawerKey])){ self.rightDrawerViewController = controller; } - + if ((controller = [coder decodeObjectForKey:MMDrawerCenterKey])){ self.centerViewController = controller; } - + if ((openside = [coder decodeIntegerForKey:MMDrawerOpenSideKey])){ [self openDrawerSide:openside animated:false completion:nil]; } @@ -253,11 +253,11 @@ -(void)toggleDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated complet } else { if((drawerSide == MMDrawerSideLeft && - self.openSide == MMDrawerSideLeft) || + self.openSide == MMDrawerSideLeft) || (drawerSide == MMDrawerSideRight && - self.openSide == MMDrawerSideRight)){ - [self closeDrawerAnimated:animated completion:completion]; - } + self.openSide == MMDrawerSideRight)){ + [self closeDrawerAnimated:animated completion:completion]; + } else if(completion){ completion(NO); } @@ -342,7 +342,7 @@ -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity: [self setAnimatingDrawer:animated]; UIViewController * sideDrawerViewController = [self sideDrawerViewControllerForSide:drawerSide]; if (self.openSide != drawerSide) { - [self prepareToPresentDrawer:drawerSide animated:animated]; + [self prepareToPresentDrawer:drawerSide animated:animated]; } if(sideDrawerViewController){ @@ -393,28 +393,28 @@ -(void)setCenterViewController:(UIViewController *)centerViewController animated if ([self.centerViewController isEqual:centerViewController]) { return; } - - if (_centerContainerView == nil) { - //This is related to Issue #152 (https://github.com/mutualmobile/MMDrawerController/issues/152) - // also fixed below in the getter for `childControllerContainerView`. Turns out we have - // two center container views getting added to the view during init, - // because the first request self.centerContainerView.bounds was kicking off a - // viewDidLoad, which caused us to be able to fall through this check twice. - // - //The fix is to grab the bounds, and then check again that the child container view has - //not been created. - CGRect centerFrame = self.childControllerContainerView.bounds; - if(_centerContainerView == nil){ - _centerContainerView = [[MMDrawerCenterContainerView alloc] initWithFrame:centerFrame]; - [self.centerContainerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; - [self.centerContainerView setBackgroundColor:[UIColor clearColor]]; - [self.centerContainerView setOpenSide:self.openSide]; - [self.centerContainerView setCenterInteractionMode:self.centerHiddenInteractionMode]; - [self.childControllerContainerView addSubview:self.centerContainerView]; - } - } - + if (_centerContainerView == nil) { + //This is related to Issue #152 (https://github.com/mutualmobile/MMDrawerController/issues/152) + // also fixed below in the getter for `childControllerContainerView`. Turns out we have + // two center container views getting added to the view during init, + // because the first request self.centerContainerView.bounds was kicking off a + // viewDidLoad, which caused us to be able to fall through this check twice. + // + //The fix is to grab the bounds, and then check again that the child container view has + //not been created. + + CGRect centerFrame = self.childControllerContainerView.bounds; + if(_centerContainerView == nil){ + _centerContainerView = [[MMDrawerCenterContainerView alloc] initWithFrame:centerFrame]; + [self.centerContainerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + [self.centerContainerView setBackgroundColor:[UIColor clearColor]]; + [self.centerContainerView setOpenSide:self.openSide]; + [self.centerContainerView setCenterInteractionMode:self.centerHiddenInteractionMode]; + [self.childControllerContainerView addSubview:self.centerContainerView]; + } + } + UIViewController * oldCenterViewController = self.centerViewController; if(oldCenterViewController){ [oldCenterViewController willMoveToParentViewController:nil]; @@ -453,9 +453,9 @@ -(void)setCenterViewController:(UIViewController *)newCenterViewController withC //If a side drawer isn't open, there is nothing to animate... animated = NO; } - + BOOL forwardAppearanceMethodsToCenterViewController = ([self.centerViewController isEqual:newCenterViewController] == NO); - + UIViewController * oldCenterViewController = self.centerViewController; // This is related to issue 363 (https://github.com/novkostya/MMDrawerController/pull/363) // This needs to be refactored so the appearance logic is easier @@ -532,7 +532,7 @@ -(void)setCenterViewController:(UIViewController *)newCenterViewController withF [sideDrawerViewController.view setFrame:self.childControllerContainerView.bounds]; } completion:^(BOOL finished) { - + CGRect oldCenterRect = self.centerContainerView.frame; [self setCenterViewController:newCenterViewController animated:animated]; [self.centerContainerView setFrame:oldCenterRect]; @@ -542,30 +542,30 @@ -(void)setCenterViewController:(UIViewController *)newCenterViewController withF [self.centerViewController beginAppearanceTransition:YES animated:animated]; } [sideDrawerViewController beginAppearanceTransition:NO animated:animated]; - [UIView - animateWithDuration:[self animationDurationForAnimationDistance:CGRectGetWidth(self.childControllerContainerView.bounds)] - delay:MMDrawerDefaultFullAnimationDelay - options:UIViewAnimationOptionCurveEaseInOut - animations:^{ - [self.centerContainerView setFrame:self.childControllerContainerView.bounds]; - [self updateDrawerVisualStateForDrawerSide:self.openSide percentVisible:0.0]; - } - completion:^(BOOL finished) { - if (forwardAppearanceMethodsToCenterViewController) { - [self.centerViewController endAppearanceTransition]; - [self.centerViewController didMoveToParentViewController:self]; - } - [sideDrawerViewController endAppearanceTransition]; - [self resetDrawerVisualStateForDrawerSide:self.openSide]; - - [sideDrawerViewController.view setFrame:sideDrawerViewController.mm_visibleDrawerFrame]; - - [self setOpenSide:MMDrawerSideNone]; - [self setAnimatingDrawer:NO]; - if(completion){ - completion(finished); - } - }]; + [UIView + animateWithDuration:[self animationDurationForAnimationDistance:CGRectGetWidth(self.childControllerContainerView.bounds)] + delay:MMDrawerDefaultFullAnimationDelay + options:UIViewAnimationOptionCurveEaseInOut + animations:^{ + [self.centerContainerView setFrame:self.childControllerContainerView.bounds]; + [self updateDrawerVisualStateForDrawerSide:self.openSide percentVisible:0.0]; + } + completion:^(BOOL finished) { + if (forwardAppearanceMethodsToCenterViewController) { + [self.centerViewController endAppearanceTransition]; + [self.centerViewController didMoveToParentViewController:self]; + } + [sideDrawerViewController endAppearanceTransition]; + [self resetDrawerVisualStateForDrawerSide:self.openSide]; + + [sideDrawerViewController.view setFrame:sideDrawerViewController.mm_visibleDrawerFrame]; + + [self setOpenSide:MMDrawerSideNone]; + [self setAnimatingDrawer:NO]; + if(completion){ + completion(finished); + } + }]; }]; } else { @@ -706,11 +706,11 @@ -(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers{ #pragma mark - View Lifecycle - (void)viewDidLoad { - [super viewDidLoad]; + [super viewDidLoad]; [self.view setBackgroundColor:[UIColor blackColor]]; - [self setupGestureRecognizers]; + [self setupGestureRecognizers]; } -(void)viewWillAppear:(BOOL)animated{ @@ -840,11 +840,11 @@ - (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDr NSParameterAssert(drawerSide != MMDrawerSideNone); UIViewController *currentSideViewController = [self sideDrawerViewControllerForSide:drawerSide]; - + if (currentSideViewController == viewController) { return; } - + if (currentSideViewController != nil) { [currentSideViewController beginAppearanceTransition:NO animated:NO]; [currentSideViewController.view removeFromSuperview]; @@ -1015,7 +1015,7 @@ -(UIView*)childControllerContainerView{ [_childControllerContainerView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth]; [self.view addSubview:_childControllerContainerView]; } - + } return _childControllerContainerView; } @@ -1051,11 +1051,11 @@ -(void)tapGestureCallback:(UITapGestureRecognizer *)tapGesture{ } } --(void)panGestureCallback:(UIPanGestureRecognizer *)panGesture{ - switch (panGesture.state) { +-(void)screenSwipeGestureCallback:(UIScreenEdgePanGestureRecognizer *)screenGesture{ + switch (screenGesture.state) { case UIGestureRecognizerStateBegan:{ if(self.animatingDrawer){ - [panGesture setEnabled:NO]; + [screenGesture setEnabled:NO]; break; } else { @@ -1065,7 +1065,7 @@ -(void)panGestureCallback:(UIPanGestureRecognizer *)panGesture{ case UIGestureRecognizerStateChanged:{ self.view.userInteractionEnabled = NO; CGRect newFrame = self.startingPanRect; - CGPoint translatedPoint = [panGesture translationInView:self.centerContainerView]; + CGPoint translatedPoint = [screenGesture translationInView:self.centerContainerView]; newFrame.origin.x = [self roundedOriginXForDrawerConstriants:CGRectGetMinX(self.startingPanRect)+translatedPoint.x]; newFrame = CGRectIntegral(newFrame); CGFloat xOffset = newFrame.origin.x; @@ -1087,7 +1087,7 @@ -(void)panGestureCallback:(UIPanGestureRecognizer *)panGesture{ UIViewController * sideDrawerViewController = [self sideDrawerViewControllerForSide:self.openSide]; [sideDrawerViewController beginAppearanceTransition:NO animated:NO]; [sideDrawerViewController endAppearanceTransition]; - + //Drawer is about to become visible [self prepareToPresentDrawer:visibleSide animated:NO]; [visibleSideDrawerViewController endAppearanceTransition]; @@ -1111,10 +1111,10 @@ -(void)panGestureCallback:(UIPanGestureRecognizer *)panGesture{ case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateCancelled: { self.startingPanRect = CGRectNull; - CGPoint velocity = [panGesture velocityInView:self.childControllerContainerView]; + CGPoint velocity = [screenGesture velocityInView:self.childControllerContainerView]; [self finishAnimationForPanGestureWithXVelocity:velocity.x completion:^(BOOL finished) { if(self.gestureCompletion){ - self.gestureCompletion(self, panGesture); + self.gestureCompletion(self, screenGesture); } }]; self.view.userInteractionEnabled = YES; @@ -1191,6 +1191,8 @@ -(void)finishAnimationForPanGestureWithXVelocity:(CGFloat)xVelocity completion:( } -(void)updateDrawerVisualStateForDrawerSide:(MMDrawerSide)drawerSide percentVisible:(CGFloat)percentVisible{ + UIViewController * sideDrawerViewController = [self sideDrawerViewControllerForSide:drawerSide]; + [sideDrawerViewController.view setAlpha: percentVisible/2.0 + 0.5]; if(self.drawerVisualState){ self.drawerVisualState(self,drawerSide,percentVisible); } @@ -1270,7 +1272,10 @@ static inline CGFloat originXForDrawerOriginAndTargetOriginOffset(CGFloat origin #pragma mark - Helpers -(void)setupGestureRecognizers{ - UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureCallback:)]; + + UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self + action:@selector(screenSwipeGestureCallback:)]; + [pan setEdges:UIRectEdgeLeft]; [pan setDelegate:self]; [self.view addGestureRecognizer:pan]; @@ -1290,7 +1295,7 @@ -(void)prepareToPresentDrawer:(MMDrawerSide)drawer animated:(BOOL)animated{ UIViewController * sideDrawerViewControllerToPresent = [self sideDrawerViewControllerForSide:drawer]; UIViewController * sideDrawerViewControllerToHide = [self sideDrawerViewControllerForSide:drawerToHide]; - + [self.childControllerContainerView sendSubviewToBack:sideDrawerViewControllerToHide.view]; [sideDrawerViewControllerToHide.view setHidden:YES]; [sideDrawerViewControllerToPresent.view setHidden:NO]; @@ -1310,7 +1315,7 @@ -(void)updateShadowForCenterView{ centerView.layer.shadowColor = [self.shadowColor CGColor]; /** In the event this gets called a lot, we won't update the shadowPath - unless it needs to be updated (like during rotation) */ + unless it needs to be updated (like during rotation) */ if (centerView.layer.shadowPath == NULL) { centerView.layer.shadowPath = [[UIBezierPath bezierPathWithRect:self.centerContainerView.bounds] CGPath]; }