diff --git a/README.md b/README.md index 92cd2f6..ded7266 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ A UIViewController subclass for revealing a rear (left and/or right) view controller behind a front controller, inspired by the Facebook app, done right! +## NOTE (Changes from carloscorreia94) + +* Adds rightViewController panGestureRecognizer +* Adds frontOverlay (longtime ago from the issues, please let your self know if you find the bit of code stolen from you) for both rear and right view controllers, with or without gesture. ## NOTE ( Version 2.3) diff --git a/SWRevealViewController/SWRevealViewController.h b/SWRevealViewController/SWRevealViewController.h index 345dfaa..4ba710b 100755 --- a/SWRevealViewController/SWRevealViewController.h +++ b/SWRevealViewController/SWRevealViewController.h @@ -159,13 +159,13 @@ typedef NS_ENUM( NSInteger, FrontViewPosition) FrontViewPositionLeftSide, // Center position, rear view is hidden behind front controller - FrontViewPositionLeft, + FrontViewPositionLeft, // Right possition, front view is presented right-offseted by rearViewRevealWidth - FrontViewPositionRight, + FrontViewPositionRight, // Right most possition, front view is presented right-offseted by rearViewRevealWidth+rearViewRevealOverdraw - FrontViewPositionRightMost, + FrontViewPositionRightMost, // Front controller is removed from view. Animated transitioning from this state will cause the same // effect than animating from FrontViewPositionRightMost. Use this instead of FrontViewPositionRightMost when @@ -228,6 +228,7 @@ typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType) // you still need to call this method, just don't add it to any of your views. The default setup allows you to dissable // user interactions on your controller views without affecting the recognizer. - (UIPanGestureRecognizer*)panGestureRecognizer; +- (UIPanGestureRecognizer*)rightPanGestureRecognizer; // The following method will provide a tapGestureRecognizer suitable to be added to any view on the frontController // for concealing the rear views. By default no tap recognizer is created or added to any view, however if you call this method after @@ -307,6 +308,14 @@ typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType) // clipping your front view to this controller bounds. @property (nonatomic) BOOL extendsPointInsideHit; + +// An overlay view that is laid on top of the frontview when rearview is displayed. +// It prevents the front view from accepting any touched when it is pushed to the side. +@property (strong, nonatomic) UIView *frontOverlayView; +@property (strong, nonatomic) UIButton *overlayButton; + +@property (assign, nonatomic) BOOL shouldUseFrontViewOverlay; + /* The class properly handles all the relevant calls to appearance methods on the contained controllers. Moreover you can assign a delegate to let the class inform you on positions and animation activity */ diff --git a/SWRevealViewController/SWRevealViewController.m b/SWRevealViewController/SWRevealViewController.m index d378d13..68a886c 100755 --- a/SWRevealViewController/SWRevealViewController.m +++ b/SWRevealViewController/SWRevealViewController.m @@ -586,6 +586,7 @@ @interface SWRevealViewController() { SWRevealView *_contentView; UIPanGestureRecognizer *_panGestureRecognizer; + UIPanGestureRecognizer *_rightPanGestureRecognizer; UITapGestureRecognizer *_tapGestureRecognizer; FrontViewPosition _frontViewPosition; FrontViewPosition _rearViewPosition; @@ -843,7 +844,8 @@ - (void)revealToggleAnimated:(BOOL)animated FrontViewPosition toggledFrontViewPosition = FrontViewPositionLeft; if (_frontViewPosition <= FrontViewPositionLeft) toggledFrontViewPosition = FrontViewPositionRight; - + + [self setFrontViewPosition:toggledFrontViewPosition animated:animated]; } @@ -917,6 +919,18 @@ - (UIPanGestureRecognizer*)panGestureRecognizer return _panGestureRecognizer; } +- (UIPanGestureRecognizer*)rightPanGestureRecognizer +{ + if ( _rightPanGestureRecognizer == nil ) + { + _rightPanGestureRecognizer = [[SWRevealViewControllerPanGestureRecognizer alloc] initWithTarget:self action:@selector(_handleRevealGesture:)]; + _rightPanGestureRecognizer.delegate = self; + [_contentView.frontView addGestureRecognizer:_rightPanGestureRecognizer]; + } + return _rightPanGestureRecognizer; +} + + - (UITapGestureRecognizer*)tapGestureRecognizer { @@ -1016,6 +1030,7 @@ - (void)_notifyPanGestureEnded if ( [_delegate respondsToSelector:@selector(revealControllerPanGestureEnded:)] ) [_delegate revealControllerPanGestureEnded:self]; + } @@ -1108,8 +1123,12 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)recognizer // only allow gesture if no previous request is in process if ( _animationQueue.count == 0 ) { - if ( recognizer == _panGestureRecognizer ) + if ( recognizer == _panGestureRecognizer) return [self _panGestureShouldBegin]; + + if ( recognizer == _rightPanGestureRecognizer) + return [self _rightPanGestureShouldBegin]; + if ( recognizer == _tapGestureRecognizer ) return [self _tapGestureShouldBegin]; @@ -1121,7 +1140,7 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)recognizer - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { - if ( gestureRecognizer == _panGestureRecognizer ) + if ( gestureRecognizer == _panGestureRecognizer || gestureRecognizer == _rightPanGestureRecognizer ) { if ( [_delegate respondsToSelector:@selector(revealController:panGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:)] ) if ( [_delegate revealController:self panGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer] != NO ) @@ -1185,6 +1204,38 @@ - (BOOL)_panGestureShouldBegin } +- (BOOL)_rightPanGestureShouldBegin +{ + // forbid gesture if the initial translation is not horizontal + UIView *recognizerView = _rightPanGestureRecognizer.view; + CGPoint translation = [_rightPanGestureRecognizer translationInView:recognizerView]; + // NSLog( @"translation:%@", NSStringFromCGPoint(translation) ); + // if ( fabs(translation.y/translation.x) > 1 ) + // return NO; + + // forbid gesture if the following delegate is implemented and returns NO + if ( [_delegate respondsToSelector:@selector(revealControllerPanGestureShouldBegin:)] ) + if ( [_delegate revealControllerPanGestureShouldBegin:self] == NO ) + return NO; + + CGFloat xLocation = [_rightPanGestureRecognizer locationInView:recognizerView].x; + CGFloat width = recognizerView.bounds.size.width; + + BOOL draggableBorderAllowing = ( + /*_frontViewPosition != FrontViewPositionLeft ||*/ _draggableBorderWidth == 0.0f || + (_rearViewController && xLocation <= _draggableBorderWidth) || + (_rightViewController && xLocation >= (width - _draggableBorderWidth)) ); + + + BOOL translationForbidding = ( _frontViewPosition == FrontViewPositionLeft && + ((_rearViewController == nil && translation.x > 0) || (_rightViewController == nil && translation.x < 0)) ); + + // allow gesture only within the bounds defined by the draggableBorderWidth property + return draggableBorderAllowing && !translationForbidding ; +} + + + #pragma mark - Gesture Based Reveal - (void)_handleTapGesture:(UITapGestureRecognizer *)recognizer @@ -1605,8 +1656,50 @@ - (void)_performTransitionOperation:(SWRevealControllerOperation)operation withV - (void (^)(void)) _deploymentForViewController:(UIViewController*)controller inView:(UIView*)view appear:(BOOL)appear disappear:(BOOL)disappear { - if ( appear ) return [self _deployForViewController:controller inView:view]; - if ( disappear ) return [self _undeployForViewController:controller]; + if ( appear ) { + if (controller == _rightViewController || controller == _rearViewController) { + //Add overlay if requested + if (_shouldUseFrontViewOverlay) { + //Create + if (!_frontOverlayView) { + self.frontOverlayView = [[UIView alloc] initWithFrame:self.frontViewController.view.bounds]; + _frontOverlayView.backgroundColor = [UIColor blackColor]; + _frontOverlayView.alpha = 0.0; + _overlayButton = [[UIButton alloc] initWithFrame:_frontOverlayView.bounds]; + [_frontOverlayView addSubview:_overlayButton]; + + } else { + [_overlayButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; + } + _frontOverlayView.alpha = 0.0; + + void (^animations)() = ^() + { + _frontOverlayView.alpha = 0.5; + }; + + + [UIView animateWithDuration:_toggleAnimationDuration delay:0.0 + options:UIViewAnimationOptionCurveEaseOut animations:animations completion:NULL]; + + if (controller == _rearViewController) + [_overlayButton addTarget:self action:@selector(revealToggleAnimated:) forControlEvents:UIControlEventTouchUpInside]; + else + [_overlayButton addTarget:self action:@selector(rightRevealToggleAnimated:) forControlEvents:UIControlEventTouchUpInside]; + + [self.frontViewController.view addSubview:_frontOverlayView]; + } + + } + + return [self _deployForViewController:controller inView:view]; + } + if ( disappear ) { + if ([[_frontViewController.view subviews] containsObject:_frontOverlayView]) { + [_frontOverlayView removeFromSuperview]; + } + return [self _undeployForViewController:controller]; + } return ^{}; } @@ -1933,4 +2026,3 @@ - (void)perform // //@end -