您的位置:首页 > 移动开发

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

2014-01-17 17:20 537 查看
实现腾讯qq,新浪微博,网易等app中右拖动返回上一层的效果demo。

首先看一下效果图:





首先要理解UIWindow,UIWindow对象是所有UIView的根,管理和协调的应用程序的显示

UIWindow类是UIView的子类,可以看作是特殊的UIView。

一般应用程序只有一个UIWindow对象,即使有多个UIWindow对象,也只有一个UIWindow可以接受到用户的触屏事件。

[cpp] view
plaincopy

//window窗口

#define WINDOW [[UIApplication sharedApplication]keyWindow]

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

[cpp] view
plaincopy

//拖动手势

UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)];

//添加手势

[self.view addGestureRecognizer:panGesture];

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

首先定义所需变量:

[cpp] view
plaincopy

@interface MyNavigationViewController ()

{

CGPoint startTouch;//拖动时的开始坐标

BOOL isMoving;//是否在拖动中

UIView *blackMask;//那层黑面罩

UIImageView *lastScreenShotView;//截图

}

@property (nonatomic,retain) UIView *backgroundView;//背景

@property (nonatomic,retain) NSMutableArray *screenShotsList;//存截图的数组

@end

然后是handlePanGesture方法处理:

[cpp] view
plaincopy

//拖动手势

-(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缩放大小:

[cpp] view
plaincopy

- (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

[cpp] view
plaincopy

//把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的时候,需要把最后一个图片移除。

[cpp] view
plaincopy

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐