iPhone实现QQ等app中右拖动屏幕返回上一层视图切换的效果(继承UINavigationController)

实现腾讯qq,新浪微博,网易等app中右拖动返回上一层的效果demo。

首先看一下效果图:

iPhone实现QQ等app中右拖动屏幕返回上一层视图切换的效果(继承UINavigationController)_第1张图片       iPhone实现QQ等app中右拖动屏幕返回上一层视图切换的效果(继承UINavigationController)_第2张图片


 首先要理解UIWindow,UIWindow对象是所有UIView的根,管理和协调的应用程序的显示
 UIWindow类是UIView的子类,可以看作是特殊的UIView。
 一般应用程序只有一个UIWindow对象,即使有多个UIWindow对象,也只有一个UIWindow可以接受到用户的触屏事件。

//window窗口
#define WINDOW  [[UIApplication sharedApplication]keyWindow]

第一步:要在UIView上添加一个pan拖动的手势,并添加处发方法handlePanGesture;

//拖动手势
    UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)];
    //添加手势
    [self.view addGestureRecognizer:panGesture];

第二步:handlePanGesture方法中首先判断是不是顶级视图,是return,如果不是需要返回上一层;

首先定义所需变量:


@interface MyNavigationViewController ()
{
    CGPoint startTouch;//拖动时的开始坐标
    BOOL isMoving;//是否在拖动中
    UIView *blackMask;//那层黑面罩
    
    UIImageView *lastScreenShotView;//截图

}
@property (nonatomic,retain) UIView *backgroundView;//背景
@property (nonatomic,retain) NSMutableArray *screenShotsList;//存截图的数组


@end

然后是handlePanGesture方法处理:

//拖动手势
-(IBAction)handlePanGesture:(UIGestureRecognizer*)sender{

    //如果是顶级viewcontroller,结束
    if (self.viewControllers.count <= 1) return;

    //得到触摸中在window上拖动的过程中的xy坐标
    CGPoint translation=[sender locationInView:WINDOW];
    //状态结束,保存数据
    if(sender.state == UIGestureRecognizerStateEnded){
        NSLog(@"结束%f,%f",translation.x,translation.y);
        isMoving = NO;

        self.backgroundView.hidden = NO;
        //如果结束坐标大于开始坐标50像素就动画效果移动
        if (translation.x - startTouch.x > 50) {
            [UIView animateWithDuration:0.3 animations:^{
                //动画效果,移动
                [self moveViewWithX:320];
            } completion:^(BOOL finished) {
                //返回上一层
                [self popViewControllerAnimated:NO];
                //并且还原坐标
                CGRect frame = self.view.frame;
                frame.origin.x = 0;
                self.view.frame = frame;
            }];
            
        }else{
            //不大于50时就移动原位
            [UIView animateWithDuration:0.3 animations:^{
                //动画效果
                [self moveViewWithX:0];
            } completion:^(BOOL finished) {
                //背景隐藏
                self.backgroundView.hidden = YES;
            }];
        }
        return;
        
    }else if(sender.state == UIGestureRecognizerStateBegan){
        NSLog(@"开始%f,%f",translation.x,translation.y);
        //开始坐标
        startTouch = translation;
        //是否开始移动
        isMoving = YES;
        if (!self.backgroundView)
        {
            //添加背景
            CGRect frame = self.view.frame;
            self.backgroundView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width , frame.size.height)];
            //把backgroundView插入到Window视图上,并below低于self.view层
            [WINDOW insertSubview:self.backgroundView belowSubview:self.view];
            
            //在backgroundView添加黑色的面罩
            blackMask = [[UIView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width , frame.size.height)];
            blackMask.backgroundColor = [UIColor blackColor];
            [self.backgroundView addSubview:blackMask];
        }
        self.backgroundView.hidden = NO;

        if (lastScreenShotView) [lastScreenShotView removeFromSuperview];
        
        //数组中最后截图
        UIImage *lastScreenShot = [self.screenShotsList lastObject];
        //并把截图插入到backgroundView上,并黑色的背景下面
        lastScreenShotView = [[UIImageView alloc]initWithImage:lastScreenShot];
        [self.backgroundView insertSubview:lastScreenShotView belowSubview:blackMask];
        
    }
    
    if (isMoving) {
        [self moveViewWithX:translation.x - startTouch.x];

    }
}

以上代码实现的是在UIWindow上放一个屏幕大小的UIView *backgroundView,并且这个UIView要插入到UIWindow视图里当前UIVIew的下面,这个方法是[WINDOW insertSubview:self.backgroundView belowSubview:self.view];
然后在backgroundView上要两个view:

UIView *blackMask;//那层黑面罩
UIImageView *lastScreenShotView;//截屏图

在拖动中不断的改变blackMask透明值,改变lastScreenShotView缩放大小:

- (void)moveViewWithX:(float)x
{
    
    NSLog(@"Move to:%f",x);
    x = x>320?320:x;
    x = x<0?0:x;
    
    CGRect frame = self.view.frame;
    frame.origin.x = x;
    self.view.frame = frame;
    
    float scale = (x/6400)+0.95;//缩放大小
    float alpha = 0.4 - (x/800);//透明值
    
    //缩放scale
    lastScreenShotView.transform = CGAffineTransformMakeScale(scale, scale);
    //背景颜色透明值
    blackMask.alpha = alpha;
    
}

 另外要把当前屏转化成图片的方法,UIView转成UIImage

//把UIView转化成UIImage,实现截屏
- (UIImage *)ViewRenderImage
{
    //创建基于位图的图形上下文 Creates a bitmap-based graphics context with the specified options.:UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale),size大小,opaque是否透明,不透明(YES),scale比例缩放
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
   
    //当前层渲染到上下文
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

    //上下文形成图片
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    //结束并删除当前基于位图的图形上下文。
    UIGraphicsEndImageContext();
    //反回图片
    return img;
}

第三步:当push的时候,需要把当前图片添加存到数组中;当pop的时候,需要把最后一个图片移除。
 

#pragma UINavigationController 覆盖方法
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    //图像数组中存放一个当前的界面图像,然后再push
    [self.screenShotsList addObject:[self ViewRenderImage]];

    [super pushViewController:viewController animated:animated];
}

-(UIViewController *)popViewControllerAnimated:(BOOL)animated
{
    //移除最后一个
    [self.screenShotsList removeLastObject];
    return [super popViewControllerAnimated:animated];
}

Demo下载地址:http://download.csdn.net/detail/rhljiayou/5979139


你可能感兴趣的:(iphone)