Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save baxiang/9614311 to your computer and use it in GitHub Desktop.
Save baxiang/9614311 to your computer and use it in GitHub Desktop.
//
// MHGSwipeNavigationController.h
// SwipeNavigationController
//
// Created by 缪和光 on 28/12/2013.
// Copyright (c) 2013 Hokuang. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface MHGSwipeNavigationController : UINavigationController
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *mhg_popGestureRecognizer;
@end
//
// MHGSwipeNavigationController.m
// SwipeNavigationController
//
// Created by 缪和光 on 28/12/2013.
// Copyright (c) 2013 Hokuang. All rights reserved.
//
#import "MHGSwipeNavigationController.h"
#define KEY_WINDOW [[UIApplication sharedApplication] keyWindow]
#define TOP_VIEW (KEY_WINDOW.rootViewController.view)
@interface MHGSwipeNavigationController ()
@property (nonatomic, strong) NSMutableArray *snapshotStack;
@property (nonatomic, strong) UIImageView *snapshotImageView;
@property (nonatomic, assign) CGFloat lastTouchX;
@end
@implementation MHGSwipeNavigationController
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if (self) {
[self commonInit];
}
return self;
}
- (id)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = NO;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
[self.view addGestureRecognizer:panGestureRecognizer];
_mhg_popGestureRecognizer = panGestureRecognizer;
}
- (void)viewWillAppear:(BOOL)animated
{
[self addShadowForView];
}
#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];
}
UIImage *snapshot = [self takeSnapshot];
if (snapshot) [self.snapshotStack addObject:snapshot];
[super pushViewController:viewController animated:animated];
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
[self.snapshotStack removeLastObject];
return [super popViewControllerAnimated: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];
self.lastTouchX = point.x;
// [self addShadowForView];
} else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) {
CGRect frame = TOP_VIEW.frame;
CGFloat newX = (point.x - self.lastTouchX) + frame.origin.x;
if (newX < 0) {
return;
}
frame.origin.x = newX;
TOP_VIEW.frame = frame;
self.lastTouchX = point.x;
[self offsetImageViewForX:newX];
} else {
[self judgeToPushOrPop];
}
}
- (void)initSnapshot
{
if (!self.snapshotImageView) {
self.snapshotImageView = [[UIImageView alloc] initWithFrame:TOP_VIEW.bounds];
}
CGRect imageViewFrame = TOP_VIEW.bounds;
imageViewFrame.origin.x = -TOP_VIEW.bounds.size.width / 3 * 2;
self.snapshotImageView.frame = imageViewFrame;
}
#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 offsetImageViewForX:frame.origin.x];
} completion:^(BOOL finished) {
[self popViewControllerAnimated:NO];
self.snapshotImageView.hidden = YES;
frame.origin.x = 0;
TOP_VIEW.frame = frame;
}];
} else {
[UIView animateWithDuration:0.3 animations:^{
frame.origin.x = 0;
TOP_VIEW.frame = frame;
[self offsetImageViewForX:frame.origin.x];
} completion:^(BOOL finished) {
self.snapshotImageView.hidden = YES;
}];
}
}
- (void)offsetImageViewForX:(CGFloat)x {
CGFloat imageViewX = x / 3 * 2 -TOP_VIEW.bounds.size.width / 3 * 2;
CGRect imageViewFrame = self.snapshotImageView.frame;
imageViewFrame.origin.x = imageViewX;
self.snapshotImageView.frame = imageViewFrame;
}
- (void)addShadowForView {
UIView *shadowedView = self.view;
UIBezierPath* newShadowPath = [UIBezierPath bezierPathWithRect:shadowedView.bounds];
shadowedView.layer.masksToBounds = NO;
shadowedView.layer.shadowRadius = 10;
shadowedView.layer.shadowOpacity = 1;
shadowedView.layer.shadowColor = [[UIColor blackColor] CGColor];
shadowedView.layer.shadowOffset = CGSizeZero;
shadowedView.layer.shadowPath = [newShadowPath CGPath];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment