我有GLKit
基于应用程序的应用程序,其中显示了一些简单的对象。
一切正常,除了屏幕旋转,在此期间GLKView
不更新(-drawRect:
不调用)。因此,在旋转期间,投影矩阵不会根据动态变化的屏幕尺寸进行更新,并且对象看起来很糟糕(拉伸)。
我有GLKit
基于应用程序的应用程序,其中显示了一些简单的对象。
一切正常,除了屏幕旋转,在此期间GLKView
不更新(-drawRect:
不调用)。因此,在旋转期间,投影矩阵不会根据动态变化的屏幕尺寸进行更新,并且对象看起来很糟糕(拉伸)。
这可能是在黑暗中拍摄,因为我没有任何经验GLKit
,但我确实有经验UIView
和-drawRect:
。尝试更改相关视图的 contentMode 以重绘:
view.contentMode = UIViewContentModeRedraw;
这将告诉视图当它的边界发生变化时它需要重绘它的内容。否则,UIView
只会尝试缩放其内容(contentMode 的默认值为UIViewContentModeScaleToFill
)。这样做的原因是,缩放现有内容比重绘内容要容易得多,并且UIView
旨在尽可能高效。
这根本不是 UIKit 动画的工作方式。我在这个答案中解释了它的一半是如何工作的,但我会尝试总结相关位:
UIView
的属性链接到 CALayer 的“模型树”属性。他们瞬间变了。UIViewAnimationOptionBeginFromCurrentState
使其使用当前表示值。当然,也有一些例外(CAShapeLayer
似乎不仅仅是一个纹理矩形,UIScrollView
在计时器上滚动动画,UIView 转换完全是另一回事......)。
旋转应该如何工作是你得到一个单一的-setFrame:
,一切都被布置(并可能重新渲染),然后动画属性被动画化。默认情况下,这意味着事物将重新渲染到新尺寸,但会被拉伸以适应旧尺寸,然后随着旋转的进行设置动画(和取消拉伸)。
也就是说,GLKView
可能会有所不同。如果您使用GLKViewController
,它甚至可能会在旋转动画期间暂停渲染。您可以尝试-setNeedsDisplay
在旋转过程中调用,但这无济于事,因为框架已经设置为其最终值。
自己处理旋转动画的最简单方法可能是强制将非动画重新布局到旋转的帧,然后在渲染器中做一些捏造(虽然黑色边框和状态栏分别动画)。
或者,传统的方法是让您的 VC 仅纵向并自己处理设备方向通知,但这是一个很大的蠕虫(然后您必须担心状态栏方向,它决定了诸如触摸偏移和键盘方向之类的事情,并且在与其他 VC 之间转换时,它往往会“有趣地”交互)。
首先,确保在应用程序生命周期的早期某个时间点启用设备方向更改。
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
然后,当您的视图被实例化时,注册这样的通知。
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil];
然后-deviceOrientationDidChange:
在您的视图控制器中实现并调用-setNeedsDisplay