It sounds like you want a view that always draws its contents in the same orientation relative to the device, regardless of the orientation of the interface (status bar, etc.). So in your images, if “hello” is drawn with the “h” by the physical volume buttons, then you always want the “h” drawn by the physical volume buttons, even if the user has rotated the device (and the rest of the UI has rotated).
iOS rotates the user interface by setting the transform of your root view controller's view. You can check this in the debugger:
# Unrotated
(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>>
# Rotated with home button at the left
(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>>
So you can undo this by applying the inverse transform to your graphics context before drawing your content. But you have to adjust the origin of your graphics context too, which makes it a bit trickier.
First, you need to move the origin to the center of the view. Then you apply the inverse transform to undo the interface rotation. Then you move the origin back. Assuming your CGLayer
is the same size as your view (in portrait orientation), this should work:
- (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);
}
It's not perfect. It ends up drawing as I said: always in the same orientation relative to the device. However, because of the way interface rotation works, when the user rotates the device, it redraws the view rotated 90 degrees, and the rotates the view into the correct orientation.
I have put a test project here:
https://github.com/mayoff/stackoverflow-cglayer-unrotating
In the test project, you can see a translucent toolbar that acts normally - it rotates to the edge of the screen nearest the ground. Under that is the view that uses the drawRect:
method above to compensate for the user interface rotation.