Instantly share code, notes, and snippets.
Created
November 21, 2013 11:10
-
Star
(5)
5
You must be signed in to star a gist -
Fork
(2)
2
You must be signed in to fork a gist
-
Save siqin/7579845 to your computer and use it in GitHub Desktop.
SwipeNavigationController
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SwipeNavigationController.h | |
// cdNBA | |
// | |
// Created by Jason Lee on 13-9-17. | |
// Copyright (c) 2013年 Jason Lee. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
@interface SwipeNavigationController : UINavigationController | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SwipeNavigationController.m | |
// cdNBA | |
// | |
// Created by Jason Lee on 13-9-17. | |
// Copyright (c) 2013年 Jason Lee. All rights reserved. | |
// | |
#import "SwipeNavigationController.h" | |
#import <QuartzCore/QuartzCore.h> | |
#define KEY_WINDOW [[UIApplication sharedApplication] keyWindow] | |
#define TOP_VIEW (KEY_WINDOW.rootViewController.view) | |
static float originalScaleRate = 0.9; | |
static float originalMaskAlpha = 0.5; | |
@interface SwipeNavigationController () | |
@property (nonatomic, strong) NSMutableArray *snapshotStack; | |
@property (nonatomic, strong) UIImageView *snapshotImageView; | |
@property (nonatomic, strong) UIView *snapshotMaskView; | |
@property (nonatomic, assign) CGPoint startTouch; | |
@end | |
@implementation SwipeNavigationController | |
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil | |
{ | |
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; | |
if (self) { | |
// Custom initialization | |
} | |
return self; | |
} | |
- (void)dealloc | |
{ | |
[_snapshotStack release], _snapshotStack = nil; | |
[_snapshotImageView release], _snapshotImageView = nil; | |
[_snapshotMaskView release], _snapshotMaskView = nil; | |
// | |
[super dealloc]; | |
} | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
// Do any additional setup after loading the view. | |
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; | |
[self.view addGestureRecognizer:panGestureRecognizer]; | |
[panGestureRecognizer release], panGestureRecognizer = nil; | |
} | |
- (void)didReceiveMemoryWarning | |
{ | |
[super didReceiveMemoryWarning]; | |
// Dispose of any resources that can be recreated. | |
} | |
#pragma mark - capture last view's snapshot | |
- (UIImage *)takeSnapshot | |
{ | |
UIGraphicsBeginImageContextWithOptions(TOP_VIEW.bounds.size, TOP_VIEW.opaque, 0.0); | |
[TOP_VIEW.layer renderInContext:UIGraphicsGetCurrentContext()]; | |
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); | |
UIGraphicsEndImageContext(); | |
return snapshot; | |
} | |
#pragma mark - override push | |
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated | |
{ | |
if (!self.snapshotStack) { | |
self.snapshotStack = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; | |
} | |
UIImage *snapshot = [self takeSnapshot]; | |
if (snapshot) [self.snapshotStack addObject:snapshot]; | |
[super pushViewController:viewController animated:animated]; | |
} | |
#pragma mark - handlePanGesture | |
- (void)handlePanGesture:(UIPanGestureRecognizer *)panGestureRecognizer | |
{ | |
if (self.viewControllers.count <= 1) return ; | |
CGPoint point = [panGestureRecognizer locationInView:KEY_WINDOW]; | |
if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) { | |
[self initSnapshot]; | |
self.snapshotImageView.image = [self.snapshotStack lastObject]; | |
self.snapshotImageView.hidden = NO; | |
[TOP_VIEW.superview insertSubview:self.snapshotImageView belowSubview:TOP_VIEW]; | |
[UIView animateWithDuration:0.3 animations:^{ | |
CGRect frame = TOP_VIEW.frame; | |
frame.origin.x = point.x; | |
TOP_VIEW.frame = frame; | |
[self scaleSnapshotWithXOffset:frame.origin.x]; | |
} completion:^(BOOL finished) { | |
; | |
}]; | |
} else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) { | |
CGRect frame = TOP_VIEW.frame; | |
frame.origin.x = point.x; | |
TOP_VIEW.frame = frame; | |
[self scaleSnapshotWithXOffset:frame.origin.x]; | |
} else { | |
[self judgeToPushOrPop]; | |
} | |
} | |
- (void)initSnapshot | |
{ | |
if (!self.snapshotImageView) { | |
self.snapshotImageView = [[[UIImageView alloc] initWithFrame:TOP_VIEW.bounds] autorelease]; | |
if (!self.snapshotMaskView) { | |
self.snapshotMaskView = [[[UIView alloc] initWithFrame:self.snapshotImageView.bounds] autorelease]; | |
[self.snapshotImageView addSubview:self.snapshotMaskView]; | |
self.snapshotMaskView.backgroundColor = [UIColor colorWithWhite:0 alpha:originalMaskAlpha]; | |
} | |
} | |
self.snapshotImageView.transform = CGAffineTransformMakeScale(originalScaleRate, originalScaleRate); | |
} | |
#pragma mark - judgeToPushOrPop | |
- (void)judgeToPushOrPop | |
{ | |
__block CGRect frame = TOP_VIEW.frame; | |
if (frame.origin.x > (frame.size.width / 3)) { | |
[UIView animateWithDuration:0.3 animations:^{ | |
frame.origin.x = frame.size.width; | |
TOP_VIEW.frame = frame; | |
[self scaleSnapshotWithXOffset:frame.origin.x]; | |
} completion:^(BOOL finished) { | |
[self popViewControllerAnimated:NO]; | |
self.snapshotImageView.hidden = YES; | |
[self.snapshotStack removeLastObject]; | |
frame.origin.x = 0; | |
TOP_VIEW.frame = frame; | |
}]; | |
} else { | |
[UIView animateWithDuration:0.3 animations:^{ | |
frame.origin.x = 0; | |
TOP_VIEW.frame = frame; | |
[self scaleSnapshotWithXOffset:frame.origin.x]; | |
} completion:^(BOOL finished) { | |
self.snapshotImageView.hidden = YES; | |
}]; | |
} | |
} | |
#pragma mark - scale snapshotImageView | |
- (void)scaleSnapshotWithXOffset:(CGFloat)xOffset | |
{ | |
CGFloat rate = (1 - originalScaleRate) * (xOffset / TOP_VIEW.frame.size.width); | |
CGFloat targetRate = originalScaleRate + rate; | |
if (targetRate > 1) targetRate = 1; | |
self.snapshotImageView.transform = CGAffineTransformMakeScale(targetRate, targetRate); | |
[self scaleSnapshotMaskAlphaWithXOffset:xOffset]; | |
} | |
- (void)scaleSnapshotMaskAlphaWithXOffset:(CGFloat)xOffset | |
{ | |
CGFloat alpha = (1 - originalMaskAlpha) * (xOffset / TOP_VIEW.frame.size.width); | |
CGFloat targetAlpha = 1 - (originalMaskAlpha + alpha); | |
self.snapshotMaskView.backgroundColor = [UIColor colorWithWhite:0 alpha:targetAlpha]; | |
} | |
#pragma mark - | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment