Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 105 additions & 100 deletions MMDrawerController/MMDrawerController.m
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
}
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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];
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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){
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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];
Expand All @@ -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 {
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -1015,7 +1015,7 @@ -(UIView*)childControllerContainerView{
[_childControllerContainerView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
[self.view addSubview:_childControllerContainerView];
}

}
return _childControllerContainerView;
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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];

Expand All @@ -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];
Expand All @@ -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];
}
Expand Down