From 64e799fe38a9d1c16198169399c7c2b5ed6cce97 Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Date: Sun, 29 Jun 2014 12:34:00 +0100 Subject: [PATCH 1/3] Adds support for setting the shadow radius and opacity. --- MMDrawerController/MMDrawerController.h | 14 ++++++++++++++ MMDrawerController/MMDrawerController.m | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/MMDrawerController/MMDrawerController.h b/MMDrawerController/MMDrawerController.h index bf895cbb..ce9cbf5e 100644 --- a/MMDrawerController/MMDrawerController.h +++ b/MMDrawerController/MMDrawerController.h @@ -200,6 +200,20 @@ typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController * dr */ @property (nonatomic, assign) BOOL showsShadow; +/** + The value determining the shadow radius to use if a shadow should be drawn off of `centerViewController` when a drawer is open. + + By default, this is set to 10.0 + */ +@property (nonatomic, assign) CGFloat shadowRadius; + +/** + The value determining the shadow opacity to use if a shadow should be drawn off of `centerViewController` when a drawer is open. + + By default, this is set to 0.8 + */ +@property (nonatomic, assign) CGFloat shadowOpacity; + /** The flag determining if a custom background view should appear beneath the status bar, forcing the child content to be drawn lower than the status bar. This property is only available for > iOS 7.0 to take into account for the new behavior of the status bar. diff --git a/MMDrawerController/MMDrawerController.m b/MMDrawerController/MMDrawerController.m index 480145c4..f0e4b5c2 100644 --- a/MMDrawerController/MMDrawerController.m +++ b/MMDrawerController/MMDrawerController.m @@ -186,6 +186,8 @@ -(void)commonSetup{ [self setAnimationVelocity:MMDrawerDefaultAnimationVelocity]; [self setShowsShadow:YES]; + [self setShadowRadius:MMDrawerDefaultShadowRadius]; + [self setShadowOpacity:MMDrawerDefaultShadowOpacity]; [self setShouldStretchDrawer:YES]; [self setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeNone]; @@ -1237,8 +1239,8 @@ -(void)updateShadowForCenterView{ UIView * centerView = self.centerContainerView; if(self.showsShadow){ centerView.layer.masksToBounds = NO; - centerView.layer.shadowRadius = MMDrawerDefaultShadowRadius; - centerView.layer.shadowOpacity = MMDrawerDefaultShadowOpacity; + centerView.layer.shadowRadius = self.shadowRadius; + centerView.layer.shadowOpacity = self.shadowOpacity; /** In the event this gets called a lot, we won't update the shadowPath unless it needs to be updated (like during rotation) */ From fdeeaa3b004adf2ab310f7722483dd61499eff97 Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Date: Thu, 8 Jan 2015 05:30:15 +0000 Subject: [PATCH 2/3] - Adds the openDrawerCompletionBlock which notifies when a drawer is fully opened. - Allows to set the maximum overshoot to be used when stretching the drawer. - Allows to optionally disable the stretching of the drawer when using the parallaxVisualStateBlock. --- MMDrawerController/MMDrawerController.h | 15 +++++++++++++++ MMDrawerController/MMDrawerController.m | 12 ++++++++++-- MMDrawerController/MMDrawerVisualState.h | 4 +++- MMDrawerController/MMDrawerVisualState.m | 19 ++++++++++++++----- 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/MMDrawerController/MMDrawerController.h b/MMDrawerController/MMDrawerController.h index ce9cbf5e..6fd88b22 100644 --- a/MMDrawerController/MMDrawerController.h +++ b/MMDrawerController/MMDrawerController.h @@ -94,6 +94,7 @@ typedef NS_ENUM(NSInteger, MMDrawerOpenCenterInteractionMode) { @class MMDrawerController; typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible); +typedef void (^MMDrawerControllerOpenDrawerCompletionBlock)(MMDrawerController * drawerController, MMDrawerSide drawerSide); @interface MMDrawerController : UIViewController @@ -165,6 +166,13 @@ typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController * dr */ @property (nonatomic, assign) BOOL shouldStretchDrawer; +/** + The maximum overshoot to use when stretching the drawer. + + If not set then the overshoot is calculated based on the width of the center and drawer views. + */ +@property (nonatomic, assign) CGFloat maxOvershootForStretchingDrawer; + /** The current open side of the drawer. @@ -424,4 +432,11 @@ typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController * dr */ -(void)setGestureShouldRecognizeTouchBlock:(BOOL(^)(MMDrawerController * drawerController, UIGestureRecognizer * gesture, UITouch * touch))gestureShouldRecognizeTouchBlock; +/** + Sets a callback to be called when a drawer is fully opened. + + @param openDrawerCompletionBlock A block object to be called that allows the implementer be notified when a drawer is fully opened. + */ +-(void)setOpenDrawerCompletionBlock:(void(^)(MMDrawerController * drawerController, MMDrawerSide drawerSide))openDrawerCompletionBlock; + @end diff --git a/MMDrawerController/MMDrawerController.m b/MMDrawerController/MMDrawerController.m index 52c10b0c..af0f8f52 100644 --- a/MMDrawerController/MMDrawerController.m +++ b/MMDrawerController/MMDrawerController.m @@ -136,6 +136,7 @@ @interface MMDrawerController () { @property (nonatomic, copy) MMDrawerControllerDrawerVisualStateBlock drawerVisualState; @property (nonatomic, copy) MMDrawerGestureShouldRecognizeTouchBlock gestureShouldRecognizeTouch; @property (nonatomic, copy) MMDrawerGestureCompletionBlock gestureCompletion; +@property (nonatomic, copy) MMDrawerControllerOpenDrawerCompletionBlock openDrawerCompletion; @property (nonatomic, assign, getter = isAnimatingDrawer) BOOL animatingDrawer; @end @@ -371,6 +372,9 @@ -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity: if(completion){ completion(finished); } + if (finished && self.openDrawerCompletion) { + self.openDrawerCompletion(self,drawerSide); + } }]; } } @@ -651,6 +655,10 @@ -(void)bouncePreviewForDrawerSide:(MMDrawerSide)drawerSide distance:(CGFloat)dis } } +-(void)setOpenDrawerCompletionBlock:(void(^)(MMDrawerController * drawerController, MMDrawerSide drawerSide))openDrawerCompletionBlock{ + [self setOpenDrawerCompletion:openDrawerCompletionBlock]; +} + #pragma mark - Setting Drawer Visual State -(void)setDrawerVisualStateBlock:(void (^)(MMDrawerController *, MMDrawerSide, CGFloat))drawerVisualStateBlock{ [self setDrawerVisualState:drawerVisualStateBlock]; @@ -1172,7 +1180,7 @@ -(CGFloat)roundedOriginXForDrawerConstriants:(CGFloat)originX{ if (originX < -self.maximumRightDrawerWidth) { if (self.shouldStretchDrawer && self.rightDrawerViewController) { - CGFloat maxOvershoot = (CGRectGetWidth(self.centerContainerView.frame)-self.maximumRightDrawerWidth)*MMDrawerOvershootPercentage; + CGFloat maxOvershoot = self.maxOvershootForStretchingDrawer ?: (CGRectGetWidth(self.centerContainerView.frame)-self.maximumRightDrawerWidth)*MMDrawerOvershootPercentage; return originXForDrawerOriginAndTargetOriginOffset(originX, -self.maximumRightDrawerWidth, maxOvershoot); } else{ @@ -1182,7 +1190,7 @@ -(CGFloat)roundedOriginXForDrawerConstriants:(CGFloat)originX{ else if(originX > self.maximumLeftDrawerWidth){ if (self.shouldStretchDrawer && self.leftDrawerViewController) { - CGFloat maxOvershoot = (CGRectGetWidth(self.centerContainerView.frame)-self.maximumLeftDrawerWidth)*MMDrawerOvershootPercentage; + CGFloat maxOvershoot = self.maxOvershootForStretchingDrawer ?: (CGRectGetWidth(self.centerContainerView.frame)-self.maximumLeftDrawerWidth)*MMDrawerOvershootPercentage; return originXForDrawerOriginAndTargetOriginOffset(originX, self.maximumLeftDrawerWidth, maxOvershoot); } else{ diff --git a/MMDrawerController/MMDrawerVisualState.h b/MMDrawerController/MMDrawerVisualState.h index 7cb8fff1..d92c6d2d 100644 --- a/MMDrawerController/MMDrawerVisualState.h +++ b/MMDrawerController/MMDrawerVisualState.h @@ -53,9 +53,11 @@ Creates a parallax experience that slides the side drawer view controller at a different rate than the center view controller during animation. For every parallaxFactor of points moved by the center view controller, the side drawer view controller will move 1 point. Passing in 1.0 is the equivalent of a applying a sliding animation, while passing in MAX_FLOAT is the equivalent of having no animation at all. @param parallaxFactor The amount of parallax applied to the side drawer conroller. This value must be greater than 1.0. The closer the value is to 1.0, the faster the side drawer view controller will be parallaxing. - + @param shouldStretchDrawer Determines whether or not to strectch the drawer when the percentVisible is greater than 1.0. It is YES by default if using the first method. + @return The visual state block. */ +(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor; ++(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor shouldStretchDrawer:(BOOL)shouldStretchDrawer; @end diff --git a/MMDrawerController/MMDrawerVisualState.m b/MMDrawerController/MMDrawerVisualState.m index 013d019a..f7112685 100644 --- a/MMDrawerController/MMDrawerVisualState.m +++ b/MMDrawerController/MMDrawerVisualState.m @@ -113,7 +113,12 @@ +(MMDrawerControllerDrawerVisualStateBlock)swingingDoorVisualStateBlock{ return visualStateBlock; } -+(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor{ ++(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor +{ + return [self parallaxVisualStateBlockWithParallaxFactor:parallaxFactor shouldStretchDrawer:YES]; +} + ++(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor shouldStretchDrawer:(BOOL)shouldStretchDrawer{ MMDrawerControllerDrawerVisualStateBlock visualStateBlock = ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){ NSParameterAssert(parallaxFactor >= 1.0); @@ -126,8 +131,10 @@ +(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxF transform = CATransform3DMakeTranslation((-distance)/parallaxFactor+(distance*percentVisible/parallaxFactor), 0.0, 0.0); } else{ - transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); - transform = CATransform3DTranslate(transform, drawerController.maximumLeftDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); + if (shouldStretchDrawer){ + transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); + transform = CATransform3DTranslate(transform, drawerController.maximumLeftDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); + } } } else if(drawerSide == MMDrawerSideRight){ @@ -137,8 +144,10 @@ +(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxF transform = CATransform3DMakeTranslation((distance)/parallaxFactor-(distance*percentVisible)/parallaxFactor, 0.0, 0.0); } else{ - transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); - transform = CATransform3DTranslate(transform, -drawerController.maximumRightDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); + if (shouldStretchDrawer){ + transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); + transform = CATransform3DTranslate(transform, -drawerController.maximumRightDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); + } } } From 86024a9b8169cb510c95c56230fdf779897d9930 Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Date: Thu, 8 Jan 2015 19:57:50 +0000 Subject: [PATCH 3/3] Allows the animationVelocity to be calculated on demand based on the actual width of the left or right drawer. --- MMDrawerController/MMDrawerController.m | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/MMDrawerController/MMDrawerController.m b/MMDrawerController/MMDrawerController.m index af0f8f52..d77074c2 100644 --- a/MMDrawerController/MMDrawerController.m +++ b/MMDrawerController/MMDrawerController.m @@ -256,7 +256,8 @@ -(void)toggleDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated complet } -(void)closeDrawerAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion{ - [self closeDrawerAnimated:animated velocity:self.animationVelocity animationOptions:UIViewAnimationOptionCurveEaseInOut completion:completion]; + CGFloat animationVelocity = self.animationVelocity ?: (self.openSide == MMDrawerSideLeft ? self.maximumLeftDrawerWidth : self.maximumRightDrawerWidth) * 3.0; + [self closeDrawerAnimated:animated velocity:animationVelocity animationOptions:UIViewAnimationOptionCurveEaseInOut completion:completion]; } -(void)closeDrawerAnimated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion{ @@ -318,8 +319,9 @@ -(void)closeDrawerAnimated:(BOOL)animated velocity:(CGFloat)velocity animationOp -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated completion:(void (^)(BOOL finished))completion{ NSParameterAssert(drawerSide != MMDrawerSideNone); - - [self openDrawerSide:drawerSide animated:animated velocity:self.animationVelocity animationOptions:UIViewAnimationOptionCurveEaseInOut completion:completion]; + + CGFloat animationVelocity = self.animationVelocity ?: (drawerSide == MMDrawerSideLeft ? self.maximumLeftDrawerWidth : self.maximumRightDrawerWidth) * 3.0; + [self openDrawerSide:drawerSide animated:animated velocity:animationVelocity animationOptions:UIViewAnimationOptionCurveEaseInOut completion:completion]; } -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion{ @@ -1279,7 +1281,16 @@ unless it needs to be updated (like during rotation) */ } -(NSTimeInterval)animationDurationForAnimationDistance:(CGFloat)distance{ - NSTimeInterval duration = MAX(distance/self.animationVelocity,MMDrawerMinimumAnimationDuration); + CGFloat animationVelocity = self.animationVelocity; + if (!animationVelocity){ + if (self.openSide == MMDrawerSideNone){ + animationVelocity = MMDrawerDefaultAnimationVelocity; + } + else{ + animationVelocity = (self.openSide == MMDrawerSideLeft ? self.maximumLeftDrawerWidth : self.maximumRightDrawerWidth) * 3.0; + } + } + NSTimeInterval duration = MAX(distance/animationVelocity,MMDrawerMinimumAnimationDuration); return duration; }