手势移除控制器(UIPanGestureRecognizer + UINavigationController)

//
//  CZNavigationController.m
//  手势移除控制器
//
//  Created by pkxing on 14/12/10.
//  Copyright (c) 2014年 梦醒. All rights reserved.
//

// 图片透明度最小值
#define PKMinAlpha 0.5
// 动画时间
#define PKDuration 0.1
// 手势最大速率
#define PKMaxVelocity 800
// 阴影不透明度
#define PKShadowOpacity 0.3
// 阴影偏移量
#define PKShadowOffset  CGSizeMake(-3, 0)
// 阴影颜色
#define PKShadowColor  [UIColor blackColor].CGColor
#import "CZNavigationController.h"
@interface CZNavigationController()<UINavigationControllerDelegate>
/** 所有控制器截图 */
@property(nonatomic,strong) NSMutableArray *images;
/** 左边显示的 imageView */
@property(nonatomic,strong) UIImageView *imageView;
/** 导航控制器view的宽度 */
@property(nonatomic,assign) CGFloat  viewWidth;
/** 子控制器的个数 */
@property(nonatomic,assign) int  vcCount;
@end

@implementation CZNavigationController

#pragma mark - 懒加载方法
/**
 *  懒加载 imageView。
 */
- (UIImageView *)imageView {
    if(_imageView == nil) {
        _imageView = [[UIImageView alloc] init];
        CGRect frame = self.view.bounds;
        frame.origin.x -= frame.size.width;
        _imageView.frame = frame;
        [self.view insertSubview:_imageView belowSubview:self.navigationBar];
    }
    return _imageView;
}

- (NSMutableArray *)images {
    if (_images == nil) {
        _images = [NSMutableArray array];
    }
    return  _images;
}
#pragma mark - 生命周期方法
- (void)viewDidLoad {
    [super viewDidLoad];
    self.viewWidth = self.view.frame.size.width;
    // KVO监听vcCount值的变化
    [self addObserver];
    // 设置代理
    self.delegate = self;
    // 添加拖拽手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(draging:)];
    [self.view addGestureRecognizer:pan];
}

- (void)dealloc {
    [self removeObserver];
}

#pragma mark - KVO 属性监听方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"vcCount"]) {
        [self captureScreenShot];
    }
}

- (void)addObserver{
    [self addObserver:self forKeyPath:@"vcCount" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)removeObserver{
    [self removeObserver:self forKeyPath:@"vcCount"];
}

#pragma mark - 监听拖拽手势
/**
 *  监听拖拽手势
 */
- (void)draging:(UIPanGestureRecognizer *)recognizer{
    // 如果导航控制器中只有一个子控制器,则不响应拖拽手势
    if (self.viewControllers.count <= 1) return;
    // 获得拖拽的位置
    CGPoint translationPoint = [recognizer translationInView:self.view];
    // 获得水平方法平移的值
    CGFloat translationX = translationPoint.x;
    // 只能向左拖拽(translationX<0表示往右边拖拽)
    if (translationX <= 0){
        [self settingTransform:0.0];
        return;
    }
    // 手势结束或手势被取消
    if (recognizer.state == UIGestureRecognizerStateEnded
        || recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStatePossible  || recognizer.state == UIGestureRecognizerStateFailed) { // 拖拽结束或正在拖拽
        // 计算拖拽速度
        CGPoint velocity = [recognizer velocityInView:self.view];
        // 每秒移动多少个点
        CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
        
        // 如果拖拽速度大于PKMaxVelocity 或 拖拽距离大于导航控制器view宽度的一半,则出栈
        BOOL pop = (magnitude > PKMaxVelocity) || (translationX > self.viewWidth * 0.5);
        [UIView animateWithDuration:PKDuration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
            [self settingTransform:(pop ? self.viewWidth :0)];
        } completion:^(BOOL finished) {
            if (pop) {
                [self popViewControllerAnimated:NO];
                [self settingTransform:0];
                self.vcCount = self.viewControllers.count;
            }
            [_imageView removeFromSuperview];
            _imageView = nil;
        }];
    } else if(recognizer.state == UIGestureRecognizerStateBegan) { // 开始拖拽
        [self.view sendSubviewToBack:self.imageView];
        self.topViewController.view.layer.shadowOffset = PKShadowOffset;
        self.topViewController.view.layer.shadowColor = PKShadowColor;
        self.topViewController.view.layer.shadowOpacity = PKShadowOpacity;
    } else { // 正在拖拽
        if (self.imageView.image == nil) {
            self.imageView.image = [self.images lastObject];
        }
        // 移动导航控制器的view和imageView
        [self settingTransform:translationX];
    }
}

/**
 *  设置导航控制器和imageView的transform
 */
- (void)settingTransform:(CGFloat)translationX{
    self.topViewController.view.layer.transform = CATransform3DMakeTranslation(translationX, 0, 0);
    self.imageView.layer.transform = CATransform3DMakeTranslation(translationX, 0, 0);
    if (translationX == 0) {
        self.topViewController.view.layer.shadowOpacity = 0.0;
        self.navigationBar.alpha = 1.0;
    } else {
        // 控制imageView 的透明度
        CGFloat alpha = 1 - (translationX / self.viewWidth);
        self.navigationBar.alpha = MAX(0.8, alpha);
    }
}

/**
 *  屏幕截图
 */
- (void)captureScreenShot{
    [self.images removeAllObjects];
    int count = self.viewControllers.count;
    if (count <= 1) return;
    dispatch_async(dispatch_get_main_queue(), ^{
        UIViewController *controller = self.viewControllers[count - 2];
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, 0.0);
        [controller.view.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [self.images addObject:image];
    });
}

#pragma mark - UINavigationControllerDelegate 方法
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    self.vcCount = self.viewControllers.count;
}
@end


发布了10 篇原创文章 · 获赞 1 · 访问量 5889

猜你喜欢

转载自blog.csdn.net/pkxwyf/article/details/41855489