看起来你想要一个视图,它始终以相对于设备的相同方向绘制其内容,而不管界面(状态栏等)的方向如何。因此,在您的图像中,如果“hello”是由物理音量按钮旁边的“h”绘制的,则无论用户是否旋转了设备(以及UI的其余部分是否旋转),您始终希望“h”被物理音量按钮旁边的“h”绘制。
iOS通过设置根视图控制器的视图的变换来旋转用户界面。您可以在调试器中检查此操作:
(lldb) po [[(id)UIApp keyWindow] recursiveDescription]
(id) $1 = 0x0b535030 <UIWindow: 0xd434a80; frame = (0 0; 320 480); layer = <UIWindowLayer: 0xd434b70>>
| <UIView: 0xb5385e0; frame = (0 20; 320 460); autoresize = W+H; layer = <CALayer: 0xb538710>>
(lldb) po [[(id)UIApp keyWindow] recursiveDescription]
(id) $2 = 0x0f036060 <UIWindow: 0xd434a80; frame = (0 0; 320 480); layer = <UIWindowLayer: 0xd434b70>>
| <UIView: 0xb5385e0; frame = (20 0; 300 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xb538710>>
因此,在绘制内容之前,可以通过将逆变换应用于图形上下文来撤消此操作。但是,您还必须调整图形上下文的原点,这使得它有点棘手。
首先,您需要将原点移动到视图的中心。然后,应用逆变换以撤消界面旋转。然后,将原点移回。假设您的CGLayer
与您的视图(在纵向方向上)具有相同的大小,则应该可以解决此问题:
- (void)drawRect:(CGRect)rect
{
if (!_cgLayer) {
[self initCGLayer];
}
CGContextRef gc = UIGraphicsGetCurrentContext();
CGContextSaveGState(gc); {
CGSize mySize = self.bounds.size;
CGSize cgLayerSize = CGLayerGetSize(_cgLayer);
CGContextTranslateCTM(gc, mySize.width / 2, mySize.height / 2);
CGContextConcatCTM(gc, CGAffineTransformInvert(self.window.rootViewController.view.transform));
CGContextTranslateCTM(gc, -cgLayerSize.width / 2, -cgLayerSize.height / 2);
CGContextDrawLayerAtPoint(gc, CGPointZero, _cgLayer);
} CGContextRestoreGState(gc);
}
这并不完美。它最终会像我说的那样绘制:始终相对于设备保持相同的方向。然而,由于界面旋转的工作方式,当用户旋转设备时,它会重新绘制视图并将其旋转90度,然后将视图旋转到正确的方向。
我在这里放了一个测试项目:
https://github.com/mayoff/stackoverflow-cglayer-unrotating
在测试项目中,您可以看到一个半透明的工具栏,它表现得很正常 - 它会旋转到最靠近地面的屏幕边缘。在其下方是视图,使用上面的
drawRect:
方法来补偿用户界面旋转。