iOS截屏功能的实现

丰誉
2023-12-01

使用场景:

本人在自定义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,小编是不建议使用的,在此也就不再粘贴代码,如有问题可留言告知,多谢!





 类似资料: