Skip to content

Instantly share code, notes, and snippets.

@siqin
Created November 21, 2013 11:10
Show Gist options
  • Save siqin/7579845 to your computer and use it in GitHub Desktop.
Save siqin/7579845 to your computer and use it in GitHub Desktop.
SwipeNavigationController
//
// 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
//
// 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