iPhone实现QQ等app中右拖动屏幕返回上一层视图切换的效果(继承UINavigationController)
2014-01-17 17:20
537 查看
实现腾讯qq,新浪微博,网易等app中右拖动返回上一层的效果demo。
首先看一下效果图:
![](http://img.blog.csdn.net/20130820102622375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmhsamlheW91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20130820102635140?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmhsamlheW91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
首先要理解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
首先看一下效果图:
首先要理解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
相关文章推荐
- iPhone实现QQ等app中右拖动屏幕返回上一层视图切换的效果(继承UINavigationController)
- iPhone实现QQ等app中右拖动屏幕返回上一层视图切换的效果(继承UINavigationController)
- UINavigationController子类化继承后,app切换主视图返回图标颜色出错
- Android实现APP引导页四种简单视图滑动切换效果ViewPager
- Iphone开发(十三)用导航控制器实现视图的分层切换(UINavigationController)
- Android中利用ViewFliper实现屏幕切换效果
- [IOS视图切换]ViewDeck类似path效果的实现
- Android入门(34)——第十一章 使用ViewFlipper实现屏幕切换动画效果
- Iphone开发(八)利用Tabbed Application模板实现多视图切换
- Android利用ViewFlipper实现屏幕切换动画效果
- Android中利用ViewFliper实现屏幕切换效果
- 写出高效清晰Layout布局文件的一些技巧--------自定义CoordinatorLayout:实现淘宝和QQ ToolBar透明渐变效果-------自定义Coordi快速返回效果
- SnakeMaker:模仿实现 即刻APP 头像拖动的残影效果
- 在多个游戏视图间切换实现效果
- Android应用中使用ViewPager实现类似QQ的界面切换效果
- mfc下鼠标拖动画面使视图移动的实现方法,类似浏览PDF时用手型鼠标移动视图的效果
- CAGradientLayer(颜色渐变) -- 实现iphone手机屏幕“滑动来解锁”动画效果
- Android利用ViewFlipper实现屏幕切换动画效果
- 原生js实现拖动图片左右弹性切换(模仿iPhone弹性拖拽的功能)