diff --git a/Classes/FlipBoardNavigationController.h b/Classes/FlipBoardNavigationController.h index 7bc8d6e..238ecc2 100644 --- a/Classes/FlipBoardNavigationController.h +++ b/Classes/FlipBoardNavigationController.h @@ -7,19 +7,28 @@ // #import +#import "UIView+Util.h" typedef void (^FlipBoardNavigationControllerCompletionBlock)(void); @interface FlipBoardNavigationController : UIViewController - +{ + CGPoint _rightPanViewCenterPoint; + BOOL _originTouchProcess; + BOOL _rightTouchProcess; + + UIView * _view_mask_fake; +} @property(nonatomic, retain) NSMutableArray *viewControllers; - +@property (nonatomic,strong) UIViewController * rightPanController; +-(void)addRightPanViewController:(UIViewController*)viewController; - (id) initWithRootViewController:(UIViewController*)rootViewController; - (void) pushViewController:(UIViewController *)viewController; - (void) pushViewController:(UIViewController *)viewController completion:(FlipBoardNavigationControllerCompletionBlock)handler; - (void) popViewController; - (void) popViewControllerWithCompletion:(FlipBoardNavigationControllerCompletionBlock)handler; +- (void) popViewController:(UIViewController*)viewControler withCompletion:(FlipBoardNavigationControllerCompletionBlock)handler; @end @interface UIViewController (FlipBoardNavigationController) diff --git a/Classes/FlipBoardNavigationController.m b/Classes/FlipBoardNavigationController.m index 2262344..b660483 100644 --- a/Classes/FlipBoardNavigationController.m +++ b/Classes/FlipBoardNavigationController.m @@ -13,6 +13,7 @@ static const CGFloat kAnimationDelay = 0.0f; static const CGFloat kOffsetTrigger = 30.0f; static const CGFloat kMaxBlackMaskAlpha = 0.8f; +static const CGFloat kViewScaleSize = 0.95f; typedef enum { @@ -67,8 +68,13 @@ - (void) loadView { _blackMask.backgroundColor = [UIColor blackColor]; _blackMask.alpha = 0.0; [self.view insertSubview:_blackMask atIndex:0]; + +} +-(void)addRightPanViewController:(UIViewController*)viewController +{ + [self.view addSubview:viewController.view]; + [self addPanGestureToView:viewController.view]; } - #pragma mark - PushViewController With Completion Block - (void) pushViewController:(UIViewController *)viewController completion:(FlipBoardNavigationControllerCompletionBlock)handler { _animationInProgress = YES; @@ -80,7 +86,7 @@ - (void) pushViewController:(UIViewController *)viewController completion:(FlipB [self.view addSubview:viewController.view]; [UIView animateWithDuration:kAnimationDuration delay:kAnimationDelay options:0 animations:^{ CGAffineTransform transf = CGAffineTransformIdentity; - [self currentViewController].view.transform = CGAffineTransformScale(transf, 0.9f, 0.9f); + [self currentViewController].view.transform = CGAffineTransformScale(transf, kViewScaleSize, kViewScaleSize); viewController.view.frame = self.view.bounds; _blackMask.alpha = kMaxBlackMaskAlpha; } completion:^(BOOL finished) { @@ -119,6 +125,7 @@ - (void) popViewControllerWithCompletion:(FlipBoardNavigationControllerCompletio [self.view bringSubviewToFront:[self previousViewController].view]; [currentVC removeFromParentViewController]; [currentVC didMoveToParentViewController:nil]; + [currentVC.view removeFromSuperview];///修正view不能释放 jack 2013-7-2 [self.viewControllers removeObject:currentVC]; _animationInProgress = NO; handler(); @@ -127,6 +134,36 @@ - (void) popViewControllerWithCompletion:(FlipBoardNavigationControllerCompletio } +- (void) popViewController:(UIViewController*)viewControler withCompletion:(FlipBoardNavigationControllerCompletionBlock)handler +{ + BOOL exist = NO; + for (UIViewController * subControler in self.viewControllers) + { + if(subControler==viewControler) + { + exist = YES; + break; + } + } + if (self.viewControllers.count < 2||!exist) { + return; + } + + UIViewController *currentVC = [self currentViewController]; + if(currentVC==viewControler) + { + [self popViewControllerWithCompletion:handler]; + return; + } + + [viewControler willMoveToParentViewController:nil]; + [viewControler removeFromParentViewController]; + [viewControler didMoveToParentViewController:nil]; + [viewControler.view removeFromSuperview]; + [self.viewControllers removeObject:viewControler]; + handler(); +} + - (void) popViewController { [self popViewControllerWithCompletion:^{}]; } @@ -140,7 +177,7 @@ - (void) rollBackViewController { self.view.transform = self.view.transform; [UIView animateWithDuration:((vc.view.frame.origin.x *kAnimationDuration)/self.view.frame.size.width) delay:kAnimationDelay options:0 animations:^{ CGAffineTransform transf = CGAffineTransformIdentity; - nvc.view.transform = CGAffineTransformScale(transf, 0.9f, 0.9f); + nvc.view.transform = CGAffineTransformScale(transf, kViewScaleSize, kViewScaleSize); vc.view.frame = rect; _blackMask.alpha = kMaxBlackMaskAlpha; } completion:^(BOOL finished) { @@ -179,25 +216,61 @@ - (void) addPanGestureToView:(UIView*)view UIPanGestureRecognizer* panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(gestureRecognizerDidPan:)]; panGesture.cancelsTouchesInView = YES; + panGesture.maximumNumberOfTouches = 1; panGesture.delegate = self; [view addGestureRecognizer:panGesture]; [_gestures addObject:panGesture]; - panGesture = nil; -} +} #pragma mark - Gesture recognizer - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { UIViewController * vc = [self.viewControllers lastObject]; _panOrigin = vc.view.frame.origin; gestureRecognizer.enabled = YES; + _rightPanViewCenterPoint = self.rightPanController.view.center; return !_animationInProgress; } - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { - return YES; + return NO; } +-(void)rightPanViewControllerAnimationEndWithDirection:(PanDirection)direction +{ + _animationInProgress = YES; + CGRect frame = CGRectZero; + switch (direction) + { + case PanDirectionLeft: + break; + case PanDirectionRight: + frame.origin = CGPointMake(320, 0); + default: + break; + } + frame.size = self.rightPanController.view.frame.size; + + [UIView animateWithDuration:((self.rightPanController.view.frame.origin.x *kAnimationDuration)/self.view.frame.size.width) + animations:^() + { + if(direction==PanDirectionRight) + { + [self.view exchangeSubview:[self currentViewController].view + withSubview:_blackMask]; + } + self.rightPanController.view.frame =frame; + CGFloat newAlpha = direction==PanDirectionLeft?kMaxBlackMaskAlpha:0.0; + _blackMask.alpha = newAlpha; + + CGAffineTransform transf = CGAffineTransformIdentity; + CGFloat newTransformValue = direction==PanDirectionLeft?kViewScaleSize:1.0; + [self currentViewController].view.transform = CGAffineTransformScale(transf,newTransformValue,newTransformValue); + if(direction==PanDirectionRight) + [self currentViewController].view.userInteractionEnabled = YES; + _animationInProgress = NO; + }]; +} - (void) gestureRecognizerDidPan:(UIPanGestureRecognizer*)panGesture { if(_animationInProgress) return; @@ -205,8 +278,69 @@ - (void) gestureRecognizerDidPan:(UIPanGestureRecognizer*)panGesture { CGFloat x = currentPoint.x + _panOrigin.x; CGFloat offset = 0; - UIViewController * vc ; - vc = [self currentViewController]; + PanDirection panDirection = PanDirectionNone; + CGPoint vel = [panGesture velocityInView:self.view]; + if (vel.x > kOffsetTrigger) { + panDirection = PanDirectionRight; + } else { + panDirection = PanDirectionLeft; + } + + BOOL moveLeft = vel.x<1; + UIViewController * vc= [self currentViewController]; + + if(self.rightPanController&&self.rightPanController.view.frame.origin.x==0&&moveLeft) + return; + if(self.rightPanController&&//是否存在右侧的panViewController + ((moveLeft&&_rightPanController.view.center.x>160)||//向左滑入rightPanView + (!moveLeft&&_rightPanController.view.center.x<480))&&//向右推出rightPanView + !_originTouchProcess)//当前是否正在处理原有的touch事件 + { + if([self.view.subviews indexOfObject:self.currentViewController.view]> + [self.view.subviews indexOfObject:_blackMask]) + { + [self.view exchangeSubview:[self currentViewController].view + withSubview:_blackMask]; + } + [self currentViewController].view.userInteractionEnabled = NO; + _rightTouchProcess = YES; + vc = self.rightPanController; + CGPoint center = CGPointMake(_rightPanViewCenterPoint.x+currentPoint.x, vc.view.center.y); + + offset = CGRectGetWidth(self.rightPanController.view.frame) - x; + CGAffineTransform transf = CGAffineTransformIdentity; + CGFloat percentValue = abs(currentPoint.x)/320.0; + CGFloat newAlphaValue = percentValue* kMaxBlackMaskAlpha; + BOOL rightPanIsShow = _rightPanViewCenterPoint.x==160; + newAlphaValue = rightPanIsShow?1-newAlphaValue:newAlphaValue; + CGFloat newTransformValueFRTL = 1-(1-kViewScaleSize)*percentValue; + CGFloat newTransformValueFLTR = kViewScaleSize+(1-kViewScaleSize)*percentValue; + + CGFloat newTransformValue = rightPanIsShow?newTransformValueFLTR:newTransformValueFRTL; + [self currentViewController].view.transform = CGAffineTransformScale(transf,newTransformValue,newTransformValue); + _blackMask.alpha = newAlphaValue; + + if(center.x<160) + { + vc.view.center = CGPointMake(160, vc.view.center.y); + [self currentViewController].view.userInteractionEnabled = YES; + return; + } + vc.view.center = center; + + } + if(_rightTouchProcess) + { + if (panGesture.state == UIGestureRecognizerStateEnded || + panGesture.state == UIGestureRecognizerStateCancelled){ + panDirection = moveLeft?PanDirectionLeft:PanDirectionRight; + _rightTouchProcess = NO; + [self rightPanViewControllerAnimationEndWithDirection:panDirection]; + + } + return; + } + _originTouchProcess = YES; offset = CGRectGetWidth(vc.view.frame) - x; vc.view.frame = [self getSlidingRectForOffset:offset]; @@ -218,15 +352,8 @@ - (void) gestureRecognizerDidPan:(UIPanGestureRecognizer*)panGesture { _blackMask.alpha = newAlphaValue; - PanDirection panDirection = PanDirectionNone; - CGPoint vel = [panGesture velocityInView:self.view]; - if (vel.x > kOffsetTrigger) { - panDirection = PanDirectionRight; - } else { - panDirection = PanDirectionLeft; - } - if (panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled) { + _originTouchProcess = NO; [self completeSlidingAnimationWithDirection:panDirection]; } } diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo.xcodeproj/project.pbxproj b/Sample/FlipViewControllerDemo/FlipViewControllerDemo.xcodeproj/project.pbxproj index 148133c..3a6b66a 100644 --- a/Sample/FlipViewControllerDemo/FlipViewControllerDemo.xcodeproj/project.pbxproj +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2849886C176325DA0079F801 /* UIView+Util.m in Sources */ = {isa = PBXBuildFile; fileRef = 2849886B176325DA0079F801 /* UIView+Util.m */; }; 99B0A1061731743800253408 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99B0A1051731743800253408 /* UIKit.framework */; }; 99B0A1081731743800253408 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99B0A1071731743800253408 /* Foundation.framework */; }; 99B0A10A1731743800253408 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99B0A1091731743800253408 /* CoreGraphics.framework */; }; @@ -43,6 +44,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 2849886A176325DA0079F801 /* UIView+Util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Util.h"; sourceTree = ""; }; + 2849886B176325DA0079F801 /* UIView+Util.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Util.m"; sourceTree = ""; }; 99B0A1021731743800253408 /* FlipViewControllerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlipViewControllerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 99B0A1051731743800253408 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 99B0A1071731743800253408 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -139,6 +142,8 @@ 99B0A143173174FB00253408 /* Classes */, 99B0A1141731743800253408 /* AppDelegate.h */, 99B0A1151731743800253408 /* AppDelegate.m */, + 2849886A176325DA0079F801 /* UIView+Util.h */, + 2849886B176325DA0079F801 /* UIView+Util.m */, 99B0A11D1731743800253408 /* MainStoryboard_iPhone.storyboard */, 99B0A1201731743800253408 /* MainStoryboard_iPad.storyboard */, 99B0A1231731743800253408 /* ViewController.h */, @@ -216,6 +221,7 @@ 99B0A0FE1731743800253408 /* Sources */, 99B0A0FF1731743800253408 /* Frameworks */, 99B0A1001731743800253408 /* Resources */, + 285BE8241761B85D00250AC9 /* ShellScript */, ); buildRules = ( ); @@ -300,6 +306,19 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 285BE8241761B85D00250AC9 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$CODESIGNING_FOLDER_PATH\" >/tmp/\"$USER.ident\" && echo \"$CODE_SIGN_IDENTITY\" >>/tmp/\"$USER.ident\" && exit;"; + }; 99B0A1291731743800253408 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -326,6 +345,7 @@ 99B0A146173174FB00253408 /* FlipBoardNavigationController.m in Sources */, 99B0A15017317AF000253408 /* ChildViewController.m in Sources */, 99B0A15317317C7400253408 /* AnotherViewController.m in Sources */, + 2849886C176325DA0079F801 /* UIView+Util.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/AnotherViewController.m b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/AnotherViewController.m index 4c700ba..a8535ca 100644 --- a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/AnotherViewController.m +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/AnotherViewController.m @@ -27,6 +27,19 @@ - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. + + UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [btn addTarget:self + action:@selector(popController:) + forControlEvents:UIControlEventTouchUpInside]; + btn.frame =CGRectMake(100, 100, 100, 100); + [self.view addSubview:btn]; +} + +-(void)popController:(id)sender +{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"TTT" + object:nil]; } - (void)didReceiveMemoryWarning diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ChildViewController.m b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ChildViewController.m index d1c6548..fb2a37b 100644 --- a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ChildViewController.m +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ChildViewController.m @@ -27,6 +27,21 @@ - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(test:) + name:@"TTT" + object:nil]; +} + +-(void)test:(id)sender +{ + [self.flipboardNavigationController popViewController:self + withCompletion:^() + { + NSLog(@"finish"); + [[NSNotificationCenter defaultCenter] removeObserver:nil]; + }]; } - (void)didReceiveMemoryWarning diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/UIView+Util.h b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/UIView+Util.h new file mode 100644 index 0000000..de1666a --- /dev/null +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/UIView+Util.h @@ -0,0 +1,14 @@ +// +// UIView+Util.h +// FlipViewControllerDemo +// +// Created by demon on 6/8/13. +// Copyright (c) 2013 Michael Henry Pantaleon. All rights reserved. +// + +#import + +@interface UIView (Util) +-(void)exchangeSubview:(UIView*)view1 + withSubview:(UIView*)view2; +@end diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/UIView+Util.m b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/UIView+Util.m new file mode 100644 index 0000000..10d6f83 --- /dev/null +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/UIView+Util.m @@ -0,0 +1,22 @@ +// +// UIView+Util.m +// FlipViewControllerDemo +// +// Created by demon on 6/8/13. +// Copyright (c) 2013 Michael Henry Pantaleon. All rights reserved. +// + +#import "UIView+Util.h" + +@implementation UIView (Util) + +-(void)exchangeSubview:(UIView*)view1 + withSubview:(UIView*)view2 +{ + int index1 = [self.subviews indexOfObject:view1]; + int index2 = [self.subviews indexOfObject:view2]; + [self exchangeSubviewAtIndex:index1 + withSubviewAtIndex:index2]; +} + +@end diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ViewController.m b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ViewController.m index 9ad5c92..3ae44ad 100644 --- a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ViewController.m +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/ViewController.m @@ -8,6 +8,7 @@ #import "ViewController.h" #import "FlipBoardNavigationController.h" + @interface ViewController () @end @@ -27,7 +28,28 @@ - (void)didReceiveMemoryWarning } - (IBAction)push:(UIButton *)sender { - UIViewController * page = [self.storyboard instantiateViewControllerWithIdentifier:@"child_vc"]; - [self.flipboardNavigationController pushViewController:page]; +// UIViewController * page = [self.storyboard instantiateViewControllerWithIdentifier:@"child_vc"]; +// [self.flipboardNavigationController pushViewController:page]; +// +// return; + UIViewController * controller = [[UIViewController alloc] init]; + controller.view.backgroundColor = [UIColor purpleColor]; + + + UITableView * tv = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 400)]; + [controller.view addSubview:tv]; + + UIViewController * panController = [[UIViewController alloc] init]; + panController.view.backgroundColor = [UIColor grayColor]; + + UITableView * tv1 = [[UITableView alloc] initWithFrame:CGRectMake(100, 0, 320, 400)]; + [panController.view addSubview:tv1]; + + self.flipboardNavigationController.rightPanController =panController; + [self.flipboardNavigationController pushViewController:controller]; + + panController.view.center =CGPointMake(panController.view.frame.size.width*1.5 , + panController.view.frame.size.height/2); + [self.flipboardNavigationController addRightPanViewController:panController]; } @end diff --git a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/en.lproj/MainStoryboard_iPhone.storyboard b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/en.lproj/MainStoryboard_iPhone.storyboard index 06528a6..81504f7 100644 --- a/Sample/FlipViewControllerDemo/FlipViewControllerDemo/en.lproj/MainStoryboard_iPhone.storyboard +++ b/Sample/FlipViewControllerDemo/FlipViewControllerDemo/en.lproj/MainStoryboard_iPhone.storyboard @@ -1,5 +1,5 @@ - + @@ -85,10 +85,10 @@ - + - + @@ -112,6 +112,9 @@ + + +