diff --git a/MMDrawerController/MMDrawerController.h b/MMDrawerController/MMDrawerController.h index bf895cbb..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. @@ -200,6 +208,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. @@ -410,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 5e5df82f..93a8cb5e 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 @@ -186,6 +187,8 @@ -(void)commonSetup{ [self setAnimationVelocity:MMDrawerDefaultAnimationVelocity]; [self setShowsShadow:YES]; + [self setShadowRadius:MMDrawerDefaultShadowRadius]; + [self setShadowOpacity:MMDrawerDefaultShadowOpacity]; [self setShouldStretchDrawer:YES]; [self setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeNone]; @@ -253,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{ @@ -315,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{ @@ -369,6 +374,9 @@ -(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity: if(completion){ completion(finished); } + if (finished && self.openDrawerCompletion) { + self.openDrawerCompletion(self,drawerSide); + } }]; } } @@ -649,6 +657,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]; @@ -1176,7 +1188,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{ @@ -1186,7 +1198,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{ @@ -1251,8 +1263,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) */ @@ -1275,7 +1287,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; } 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); + } } }