GLKView在放大模式下尺寸不正确的解决方法

GLKView在放大模式下尺寸不正确的解决方法

遇到问题

最近开发了一款手机图片处理App。里面用到了GLKView来显示摄像头捕捉到的图像。

在朋友iPhone7上测试这款应用的时候,出现了一个奇怪的现象,GLView视图大小显示不正确。本该占满屏幕的视图现在只占据了屏幕的一部分。

调试发现,draw(rect)函数中的rect的宽度为320。而不是我们常说的375。

读取

1
UIScreen.main.bounds.size

得到的结果也是[320,538],不禁让人们怀疑这不是一台iPhone7,而是一台iPhone5。

原因是什么

这是什么原因呢?

仔细对比,发现这台手机的屏幕显示的文字是图标比常见的手机上的大。

原来从iPhone6和iOS8发布开始,iOS支持配置系统的视图显示效果。

从”设置”->”显示与亮度”->”视图”进入设置。

可以设置的值包括:标准、放大。

其实在新买的iPhone的设置向导里面也有这个设置项。

把手机的模式调整为标准,然后显示正常。

如何解决

问题来了,在发达模式下如何解决这个问题。

其他视图正常,只有GLKView出现这个问题。这个应该和draw函数有关。

普通视图在iOS中画是按Point进行画的,而opengl中是按像素划的。

在画的过程中是根据视图尺寸计算出屏幕尺寸的。

1
2


1
2
3
4
5
6
7
override func draw(_ rect: CGRect) {
let scale = UIScreen.main.scale
let destRect = rect.applying(CGAffineTransform(scaleX: scale, y: scale))
let size = CGSize(width: img.extent.size.width, height: img.extent.size.width * destRect.height / destRect.width )
let srcRect = CGRect(origin: CGPoint(x: img.extent.origin.x, y: img.extent.origin.y + img.extent.height - size.height), size: size)
coreImageContext.draw(img, in: destRect, from: srcRect)
}

现在计算出来的尺寸小了,在屏幕上画出来的区域也就小了

从iOS 7开始,UIScreen类多了两个属相

1
2
3
4
 @interface UIScreen : NSObject <UITraitEnvironment>
@property(nonatomic,readonly) CGRect nativeBounds NS_AVAILABLE_IOS(8_0); // Native bounds of the physical screen in pixels
@property(nonatomic,readonly) CGFloat nativeScale NS_AVAILABLE_IOS(8_0); // Native scale factor of the physical screen
@end

nativeScale属性的值就是指真正的缩放值。iPhone7标准显示模式下为2.0,放大模式下为2.34

所以把上面的代码中

1
let scale = UIScreen.main.scale

修改为

1
let scale = UIScreen.main.nativeScale

问题解决。

附带一句

以后可以根据

UIScreen.main.scale 是否等于UIScreen.main.nativeScale判断设备是不是处于标准显示模式。