使用场景:
本人在自定义UITabBarController的时候,想要实现手势滑动返回上一页面的效果,也就是仿QQ的滑动返回,这种滑动返回是基于UIPanGestureRecognizer这一手势,实现原理是在导航条Push的时候截取当前屏幕,并把截取到的图片添加的Window的视图上,让后当启用滑动手势的时候只要把当前(Push到的)视图滑动开来,就可以看到之前截取到的倾慕快照,当返回上一页面的时候再把截取的图片从Window上移除即可。遇到的问题是:小编自定义的UITabBarController是继承于UIViewControler,而不是系统的UITabBarController,底部的按钮区域是一个View,截取屏幕的时候总是不能截取到按钮区域的View;这就是第一种截屏方法,而后通过查找资料找到一种能够解决此问题的方法,也就是第二种截屏方法。
第一种截屏方法:
//获取截屏图片 - (UIImage *)getCurrentScreenShot{ UIGraphicsBeginImageContextWithOptions([[[UIApplication sharedApplication] keyWindow] bounds].size, NO, 0.0); [[[UIApplication sharedApplication] keyWindow].layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
注:第一种截图方法适合于屏幕上只有一个View的时候,效率较高,一般场景下就够用了。原理是首先创建一个和主屏幕(KeyWindow)一样大小的画布,然后通过 renderInContext方法把屏幕图层上的内容绘制到画布上,然后根据这张画布生成图片即可。
第二种截屏方法:
//截取全屏视图 -(UIImage *)getImageWithFullScreenshot { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; CGSize imageSize = CGSizeZero; //适配横屏状态 if (UIInterfaceOrientationIsPortrait(orientation) ) imageSize = [UIScreen mainScreen].bounds.size; else imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width); UIGraphicsBeginImageContextWithOptions(imageSize, NO, [UIScreen mainScreen].scale); CGContextRef context = UIGraphicsGetCurrentContext(); for (UIWindow *window in [[UIApplication sharedApplication] windows]) { CGContextSaveGState(context); CGContextTranslateCTM(context, window.center.x, window.center.y); CGContextConcatCTM(context, window.transform); CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y); // Correct for the screen orientation if(orientation == UIInterfaceOrientationLandscapeLeft) { CGContextRotateCTM(context, (CGFloat)M_PI_2); CGContextTranslateCTM(context, 0, -imageSize.width); } else if(orientation == UIInterfaceOrientationLandscapeRight) { CGContextRotateCTM(context, (CGFloat)-M_PI_2); CGContextTranslateCTM(context, -imageSize.height, 0); } else if(orientation == UIInterfaceOrientationPortraitUpsideDown) { CGContextRotateCTM(context, (CGFloat)M_PI); CGContextTranslateCTM(context, -imageSize.width, -imageSize.height); } if([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:NO]; else [window.layer renderInContext:UIGraphicsGetCurrentContext()]; CGContextRestoreGState(context); } UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
注:第二种截屏方法适用于屏幕上有多个视图的场景,原理基本和第一种方法一样,只是第二种方法不仅会绘制主屏幕的视图,它还会遍历已存在的所有window,并拼接所得到的画布。
附:此两种方法是适用于iOS 7及以后版本,除此之外还有一些过期的方法和私有API,小编是不建议使用的,在此也就不再粘贴代码,如有问题可留言告知,多谢!