iOS截取屏幕2/3比例区域后全屏显示模糊,如何实现无损显示?
解决同比例2/3区域截图并全屏无损显示的问题
首先,你遇到的模糊问题核心原因是截图的像素密度不足——当你按点尺寸截取后,全屏拉伸时像素被放大,自然就会模糊。要实现无损显示,关键是保证截图的像素数和屏幕显示的像素数匹配,同时严格保持比例一致。下面分步骤给你解决方案:
一、先计算符合屏幕比例的2/3截取区域
首先得确保你截取的区域和主屏幕比例完全一致,这样全屏显示时不需要强制拉伸(拉伸是模糊的元凶之一)。假设你要截取的是高度为屏幕2/3的同比例区域(你可以根据需求调整为面积2/3的计算逻辑):
// 获取主屏幕的尺寸与比例 CGSize screenSize = UIScreen.main.bounds.size; CGFloat screenRatio = screenSize.width / screenSize.height; // 竖屏比例,横屏的话反过来即可 // 计算目标区域:高度为屏幕的2/3,宽度按比例推导 CGFloat targetHeight = screenSize.height * 2.0 / 3.0; CGFloat targetWidth = targetHeight * screenRatio; // 让区域居中显示 CGFloat originX = (screenSize.width - targetWidth) / 2.0; CGFloat originY = (screenSize.height - targetHeight) / 2.0; CGRect captureRect = CGRectMake(originX, originY, targetWidth, targetHeight);
二、生成高清像素级截图
原来的代码可能没有明确指定屏幕的缩放因子(scale),导致截图的像素密度不够。修改你的getScreenshot方法,用屏幕原生scale来生成截图,保证像素数足够:
方式一:用传统的绘图上下文(兼容iOS 8+)
- (UIImage *)getScreenshot { // 第一步:计算符合比例的截取区域 CGSize screenSize = UIScreen.main.bounds.size; CGFloat screenRatio = screenSize.width / screenSize.height; CGFloat targetHeight = screenSize.height * 2.0 / 3.0; CGFloat targetWidth = targetHeight * screenRatio; CGFloat originX = (screenSize.width - targetWidth) / 2.0; CGFloat originY = (screenSize.height - targetHeight) / 2.0; CGRect captureRect = CGRectMake(originX, originY, targetWidth, targetHeight); // 关键:用屏幕的scale创建上下文,保证截图是像素级高清的 CGFloat screenScale = UIScreen.main.scale; UIGraphicsBeginImageContextWithOptions(captureRect.size, YES, screenScale); CGContextRef context = UIGraphicsGetCurrentContext(); // 转换坐标(CoreGraphics坐标原点在左下角,UIKit在左上角,需要翻转对齐) CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y); // 渲染整个屏幕的layer到上下文(如果是截取_shareView的话,替换成[_shareView.layer renderInContext:context]) [self.view.layer renderInContext:context]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return screenshot; }
方式二:用UIGraphicsImageRenderer(iOS 10+,更简洁)
- (UIImage *)getScreenshot { CGSize screenSize = UIScreen.main.bounds.size; CGFloat screenRatio = screenSize.width / screenSize.height; CGFloat targetHeight = screenSize.height * 2.0 / 3.0; CGFloat targetWidth = targetHeight * screenRatio; CGFloat originX = (screenSize.width - targetWidth) / 2.0; CGFloat originY = (screenSize.height - targetHeight) / 2.0; CGRect captureRect = CGRectMake(originX, originY, targetWidth, targetHeight); // 直接指定scale为屏幕原生scale UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:captureRect.size scale:UIScreen.main.scale]; UIImage *screenshot = [renderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) { CGContextRef context = rendererContext.CGContext; CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y); [self.view.layer renderInContext:context]; }]; return screenshot; }
三、全屏显示时的正确姿势
拿到高清截图后,全屏显示时要避免强制拉伸,用正确的contentMode来适配:
// 创建全屏ImageView UIImageView *fullScreenImageView = [[UIImageView alloc] initWithFrame:UIScreen.main.bounds]; fullScreenImageView.image = [self getScreenshot]; // 选择合适的适配模式:ScaleAspectFill会填满屏幕(裁剪多余部分),ScaleAspectFit会完整显示(留边) fullScreenImageView.contentMode = UIViewContentModeScaleAspectFill; fullScreenImageView.clipsToBounds = YES; // 用ScaleAspectFill时需要开启裁剪 // 关键:设置contentScaleFactor为屏幕scale,保证系统用高清像素渲染 fullScreenImageView.contentScaleFactor = UIScreen.main.scale; [self.view addSubview:fullScreenImageView];
为什么原来的代码会模糊?
原来的代码中,你用了_shareView.bounds.size作为上下文尺寸,并且scale传了0.0——虽然0.0会取当前上下文的scale,但如果_shareView的尺寸不是按屏幕比例设计的,或者截图的像素数远小于屏幕的像素数,当全屏拉伸时,像素被强制放大,就会出现模糊。现在我们通过明确使用屏幕scale生成截图,保证截图的像素密度和屏幕完全一致,再配合正确的显示模式,就能实现无损全屏显示了。
内容的提问来源于stack exchange,提问作者birdcage
相关产品推荐
相关产品推荐

