类似网易新闻客户端的滑动UINavigationViewController

SliderViewController.h


#import <UIKit/UIKit.h>
//定义镜像图片的缩放比例
#define kMirrorRate 0.98

//定义动画方向
typedef enum{
    LEFT,
    RIGHT
} AnimationDirect;

@interface SliderViewController : UINavigationController<UINavigationControllerDelegate>
{
    //存放push进去的每张镜像图
    NSMutableArray* _items;
    //记录当前页面位置
    NSInteger currIndex;
    //镜像图片的view,上一页的图片
    UIImageView* _mirrorView;
    //镜像图片的初始位置
    CGRect mirrorOrigal;
    //是否push进了一个页面,yes表示push了,no表示pop了
    BOOL isPush;
}
@end

SliderViewController.m


#import "SliderViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface SliderViewController ()

@end

@implementation SliderViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

//重写uinavigationcontroller的initwithrootviewcontroller方法
- (id)initWithRootViewController:(UIViewController *)rootViewController{
    _items = [[NSMutableArray alloc]initWithCapacity:0];
    currIndex = -1;
    self = [super initWithRootViewController:rootViewController];
    if (self) {
        //创建镜像图片的初始化大小
        _mirrorView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width*kMirrorRate, self.view.frame.size.height*kMirrorRate)];
        mirrorOrigal = _mirrorView.bounds;
        _mirrorView.center = self.view.center;
        self.delegate = self;
    }
    return self;
} // Convenience method pushes the root view controller without animation.

//重写pushviewcontroller方法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    //添加镜像view到navigation的view的superview中
    if (!_mirrorView.superview&&self.view.superview) {
        UIView* background = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        background.backgroundColor = [UIColor blackColor];
        [background addSubview:_mirrorView];
        [self.view.superview insertSubview:background belowSubview:self.view];
    }
    isPush = YES;
    currIndex++;
    [super pushViewController:viewController animated:animated];

}// Uses a horizontal slide transition. Has no effect if the view controller is already in the stack.

//重写popviewcontroller方法
- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
    isPush = NO;
    currIndex--;
    return [super popViewControllerAnimated:animated];
} // Returns the popped controller.

-(UIImage*)genPreviousViewPage{
    if ((currIndex)>=0) {
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        //把当前的整个画面导入到context中,然后通过context输出UIImage,这样就可以把整个屏幕转化为图片
        [self.view.layer renderInContext:context];
        __autoreleasing UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        //把当前页面生成的镜像保存起来
        [_items addObject:image];
        return image;
    }
    return nil;
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
   
   }
//实现回调,当成功切换了viewcontroller后回调
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    //当是push进新的viewcontroller
    if (isPush) {
        //调用产生镜像方法,把当前页面生成图片镜像
        [self genPreviousViewPage];
        if (currIndex>0) {
            //把镜像view的image设置成上一个viewcontroller的镜像图片
            [_mirrorView setImage:[_items objectAtIndex:currIndex-1]];
        }
    //如果是pop出了viewcontroller
    }else{
        if (_items.count>=1) {
            //把当前的镜像图片删除
            [_items removeLastObject];
            if (currIndex==0) {
                [_mirrorView setImage:nil];
            }else{
                //把镜像view的image设置成上一个viewcontroller的镜像图片
                [_mirrorView setImage:[_items objectAtIndex:currIndex-1]];
            }
        }
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
   

}
//当滑动手势时回调
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    if (_items.count<=1) {
        return;
    }
    UITouch* touch = [touches anyObject];
    CGPoint point = [touch locationInView:self.view];
    CGPoint preppoint  = [touch previousLocationInView:self.view];
    //计算出这次和上次的距离差
    double offset = (point.x-preppoint.x);
    //判断当前view的位置加上距离差有没有超过屏幕范围
    if (self.view.frame.origin.x+offset>=0&&self.view.frame.origin.x+offset<=self.view.frame.size.width) {
        //移动当前view的位置
        self.view.center = CGPointMake(self.view.center.x+offset, self.view.center.y);
        //缩放镜像view的大小
        _mirrorView.bounds = CGRectMake(0, 0, mirrorOrigal.size.width+(self.view.frame.origin.x/self.view.frame.size.width)*(1-kMirrorRate)*mirrorOrigal.size.width, mirrorOrigal.size.height+(self.view.frame.origin.x/self.view.frame.size.width)*(1-kMirrorRate)*mirrorOrigal.size.height);
    }
   
}
//当滑动手势结束后回调
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    if (_items.count<=1) {
        return;
    }
    //判断view当前的位置,如果超过屏幕一半则认为pop出当前页面
    if (self.view.frame.origin.x>=self.view.frame.size.width/2) {
        [self silderAnimation:RIGHT];
    }else{
        [self silderAnimation:LEFT];
    }
}
//当滑动手势中断时回调
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    if (_items.count<=1) {
        return;
    }
    if (self.view.frame.origin.x>=self.view.frame.size.width/2) {
        [self silderAnimation:RIGHT];
    }else{
        [self silderAnimation:LEFT];
    }
}
//手势结束后调用的动画效果
-(void)silderAnimation:(AnimationDirect)direct{
    switch (direct) {
        case LEFT:
        {   [self.view setUserInteractionEnabled:NO];
            [UIView animateWithDuration:0.5 animations:^{
            self.view.frame = CGRectMake(0, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
                _mirrorView.bounds = CGRectMake(0, 0, mirrorOrigal.size.width, mirrorOrigal.size.height);
            } completion:^(BOOL finished) {
                [self.view setUserInteractionEnabled:YES];
            }];
        }
            break;
        case RIGHT:{
            [self.view setUserInteractionEnabled:NO];
            [UIView animateWithDuration:0.5 animations:^{
            self.view.frame = CGRectMake(self.view.frame.size.width, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
                _mirrorView.bounds = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
            } completion:^(BOOL finished) {
                if (finished) {
                    [self.view setUserInteractionEnabled:YES];
                    [self popViewControllerAnimated
                     :NO];                 
                self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
                }
            }];
        }
            break;
        default:
            break;
    }

}

-(void)dealloc{

    if (_mirrorView.superview.superview) {
        [_mirrorView.superview removeFromSuperview];
    }   

    self.delegate = nil;
}
@end


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值