From 394acbc69b37122ef75303df5f7f64620f0d9eb5 Mon Sep 17 00:00:00 2001 From: Kevin Harwood Date: Thu, 16 May 2013 08:41:31 -0500 Subject: [PATCH 1/2] Smoother Automatic Pan Open/Closing using velocity --- MMDrawerController/MMDrawerController.m | 30 ++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/MMDrawerController/MMDrawerController.m b/MMDrawerController/MMDrawerController.m index 13edbbdc..92ac33d1 100644 --- a/MMDrawerController/MMDrawerController.m +++ b/MMDrawerController/MMDrawerController.m @@ -41,7 +41,7 @@ CGFloat const MMDrawerBezelRange = 20.0f; -CGFloat const MMDrawerPanVelocityXAnimationThreshold = 100.0f; +CGFloat const MMDrawerPanVelocityXAnimationThreshold = 200.0f; /** The amount of overshoot that is panned linearly. The remaining percentage nonlinearly asymptotes to the max percentage. */ CGFloat const MMDrawerOvershootLinearRangePercentage = 0.75f; @@ -181,10 +181,14 @@ -(void)toggleDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated complet } -(void)closeDrawerAnimated:(BOOL)animated completion:(void (^)(BOOL))completion{ + [self closeDrawerAnimated:animated velocity:self.animationVelocity animationOptions:UIViewAnimationOptionCurveEaseInOut completion:completion]; +} + +-(void)closeDrawerAnimated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL))completion{ CGRect newFrame = self.view.bounds; CGFloat distance = ABS(CGRectGetMinX(self.centerContainerView.frame)); - NSTimeInterval duration = [self animationDurationForAnimationDistance:distance]; + NSTimeInterval duration = MAX(distance/ABS(velocity),MMDrawerMinimumAnimationDuration); BOOL leftDrawerVisible = CGRectGetMinX(self.centerContainerView.frame) > 0; BOOL rightDrawerVisible = CGRectGetMinX(self.centerContainerView.frame) < 0; @@ -212,14 +216,14 @@ -(void)closeDrawerAnimated:(BOOL)animated completion:(void (^)(BOOL))completion{ [UIView animateWithDuration:(animated?duration:0.0) delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut + options:options animations:^{ [self.centerContainerView setFrame:newFrame]; [self updateDrawerVisualStateForDrawerSide:visibleSide percentVisible:0.0]; } completion:^(BOOL finished) { [sideDrawerViewController endAppearanceTransition]; - [self setOpenSide:MMDrawerSideNone]; + [self setOpenSide:MMDrawerSideNone]; [self resetDrawerVisualStateForDrawerSide:visibleSide]; if(completion){ @@ -231,6 +235,12 @@ -(void)closeDrawerAnimated:(BOOL)animated completion:(void (^)(BOOL))completion{ -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated completion:(void (^)(BOOL))completion{ NSParameterAssert(drawerSide != MMDrawerSideNone); + [self openDrawerSide:drawerSide animated:animated velocity:self.animationVelocity animationOptions:UIViewAnimationOptionCurveEaseInOut completion:completion]; +} + +-(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL))completion{ + NSParameterAssert(drawerSide != MMDrawerSideNone); + UIViewController * sideDrawerViewController = [self sideDrawerViewControllerForSide:drawerSide]; CGRect visibleRect = CGRectIntersection(self.view.bounds,sideDrawerViewController.view.frame); BOOL drawerFullyCovered = (CGRectContainsRect(self.centerContainerView.frame, visibleRect) || @@ -252,12 +262,12 @@ -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated completio } CGFloat distance = ABS(CGRectGetMinX(oldFrame)-newFrame.origin.x); - NSTimeInterval duration = [self animationDurationForAnimationDistance:distance]; + NSTimeInterval duration = MAX(distance/ABS(velocity),MMDrawerMinimumAnimationDuration); [UIView animateWithDuration:(animated?duration:0.0) delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut + options:options animations:^{ [self.centerContainerView setFrame:newFrame]; [self updateDrawerVisualStateForDrawerSide:drawerSide percentVisible:1.0]; @@ -792,10 +802,10 @@ -(void)finishAnimationForPanGestureWithXVelocity:(CGFloat)xVelocity completion:( if(self.openSide == MMDrawerSideLeft) { CGFloat midPoint = self.maximumLeftDrawerWidth / 2.0; if(xVelocity > MMDrawerPanVelocityXAnimationThreshold){ - [self openDrawerSide:MMDrawerSideLeft animated:YES completion:completion]; + [self openDrawerSide:MMDrawerSideLeft animated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if(xVelocity < -MMDrawerPanVelocityXAnimationThreshold){ - [self closeDrawerAnimated:YES completion:completion]; + [self closeDrawerAnimated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if(currentOriginX < midPoint){ [self closeDrawerAnimated:YES completion:completion]; @@ -808,10 +818,10 @@ -(void)finishAnimationForPanGestureWithXVelocity:(CGFloat)xVelocity completion:( currentOriginX = CGRectGetMaxX(self.centerContainerView.frame); CGFloat midPoint = (CGRectGetWidth(self.view.bounds)-self.maximumRightDrawerWidth) + (self.maximumRightDrawerWidth / 2.0); if(xVelocity > MMDrawerPanVelocityXAnimationThreshold){ - [self closeDrawerAnimated:YES completion:completion]; + [self closeDrawerAnimated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if (xVelocity < -MMDrawerPanVelocityXAnimationThreshold){ - [self openDrawerSide:MMDrawerSideRight animated:YES completion:completion]; + [self openDrawerSide:MMDrawerSideRight animated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if(currentOriginX > midPoint){ [self closeDrawerAnimated:YES completion:completion]; From d2f14efbcd2f2688aad39da7aabadc7d889d3aa0 Mon Sep 17 00:00:00 2001 From: Kevin Harwood Date: Thu, 16 May 2013 10:10:40 -0500 Subject: [PATCH 2/2] Made it more DRY --- MMDrawerController/MMDrawerController.m | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/MMDrawerController/MMDrawerController.m b/MMDrawerController/MMDrawerController.m index 92ac33d1..734a3c41 100644 --- a/MMDrawerController/MMDrawerController.m +++ b/MMDrawerController/MMDrawerController.m @@ -799,13 +799,15 @@ -(void)panGesture:(UIPanGestureRecognizer *)panGesture{ -(void)finishAnimationForPanGestureWithXVelocity:(CGFloat)xVelocity completion:(void(^)(BOOL finished))completion{ CGFloat currentOriginX = CGRectGetMinX(self.centerContainerView.frame); + CGFloat animationVelocity = MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2); + if(self.openSide == MMDrawerSideLeft) { CGFloat midPoint = self.maximumLeftDrawerWidth / 2.0; if(xVelocity > MMDrawerPanVelocityXAnimationThreshold){ - [self openDrawerSide:MMDrawerSideLeft animated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; + [self openDrawerSide:MMDrawerSideLeft animated:YES velocity:animationVelocity animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if(xVelocity < -MMDrawerPanVelocityXAnimationThreshold){ - [self closeDrawerAnimated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; + [self closeDrawerAnimated:YES velocity:animationVelocity animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if(currentOriginX < midPoint){ [self closeDrawerAnimated:YES completion:completion]; @@ -818,10 +820,10 @@ -(void)finishAnimationForPanGestureWithXVelocity:(CGFloat)xVelocity completion:( currentOriginX = CGRectGetMaxX(self.centerContainerView.frame); CGFloat midPoint = (CGRectGetWidth(self.view.bounds)-self.maximumRightDrawerWidth) + (self.maximumRightDrawerWidth / 2.0); if(xVelocity > MMDrawerPanVelocityXAnimationThreshold){ - [self closeDrawerAnimated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; + [self closeDrawerAnimated:YES velocity:animationVelocity animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if (xVelocity < -MMDrawerPanVelocityXAnimationThreshold){ - [self openDrawerSide:MMDrawerSideRight animated:YES velocity:MAX(ABS(xVelocity),MMDrawerPanVelocityXAnimationThreshold*2) animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; + [self openDrawerSide:MMDrawerSideRight animated:YES velocity:animationVelocity animationOptions:UIViewAnimationOptionCurveEaseOut completion:completion]; } else if(currentOriginX > midPoint){ [self closeDrawerAnimated:YES completion:completion];