GLKit的-drawRect:在屏幕旋转期间不调用

kpo*_*wer 5 screen-rotation ios auto-rotation glkit glkview

我有一个GLKit基于应用程序,显示一些简单的对象.

一切正常,除了屏幕旋转,在此期间GLKView不更新(-drawRect:未调用).因此,在旋转期间,投影矩阵不会根据动态变化的屏幕尺寸进行更新,并且对象看起来很糟糕(拉伸).

Aar*_*man 6

这可能是在黑暗中拍摄,因为我没有任何经验GLKit,但我确实有经验UIView-drawRect:.尝试更改相关视图的contentMode以重绘:

view.contentMode = UIViewContentModeRedraw;

这将告诉视图,当边界发生变化时,需要重绘它的内容.否则,UIView将只是尝试缩放它的内容(contentMode的默认值UIViewContentModeScaleToFill).这样做的原因是,缩放内容比重绘内容要容易得多,并且UIView设计得尽可能高效.


tc.*_*tc. 1

这根本不是 UIKit 动画的工作原理。我在这个答案中解释了其中一半是如何工作的,但我会尝试总结相关部分:

  • 一切都是一个有纹理的矩形。(也有一些例外,例如 CAShapeLayer,但大多数情况下都是如此。)
  • UIView的属性链接到 CALayer 的“模型树”属性。他们瞬间改变。
  • 动画通过将“表示树”属性从起始值动画化到当前模型值来工作。
  • 默认情况下,动画的起始值是先前的模型值。指定UIViewAnimationOptionBeginFromCurrentState使其使用当前的呈现值。

当然,也有一些例外(CAShapeLayer似乎不仅仅是一个纹理矩形,UIScrollView计时器上的滚动动画,UIView 过渡完全是另一回事......)。

旋转的工作原理是,您获得一个-setFrame:,所有内容都已布局(并可能重新渲染),然后可动画属性被动画化。默认情况下,这意味着事物将重新渲染到新尺寸,但会拉伸以适应旧尺寸,然后随着旋转的进行而产生动画(并取消拉伸)。

也就是说,GLKView工作方式可能会有所不同。如果您使用GLKViewController,它甚至可能在旋转动画期间暂停渲染。您可以尝试-setNeedsDisplay在旋转期间调用,但这不会有太大帮助,因为框架已经设置为其最终值。

自己处理旋转动画的最简单方法可能是强制对旋转帧进行非动画重新布局,然后在渲染器中进行一些捏造操作(尽管黑色边框和状态栏分别进行动画处理)。

或者,传统的方法是让你的 VC 仅纵向并自己处理设备方向通知,但这是一大堆蠕虫(然后你必须担心状态栏方向,它决定诸如触摸偏移和键盘方向之类的事情) ,并且在从其他 VC 过渡到/从其他 VC 过渡时,它往往会“有趣地”相互作用)。