objective-c - 如何保持 CGLayerRef 不变,即使在设备方向切换之后也是如此?

标签 objective-c ios ipad core-graphics quartz-graphics

我正在使用 CoreGraphics 将 CGLayerRef 存储到一个变量中。

我在屏幕外的 CGLayerRef 中绘制路径,然后在需要时渲染它。这很好用,因为我绘制了很多路径,这有助于提高性能。

问题发生在 iPad 的方向改变时。发生这种情况时,我需要将我的绘图保留在 CGLayerRef 中而不做任何更改,尽管框架已更改。我不想重绘里面的所有东西,因为它会很慢。

那么...我将如何保持它以前的方向?

用图片总结一下:

这是我正常的纵向方向: enter image description here

当方向切换时,我的目标是它看起来像这样: enter image description here

提前致谢

-大卫

最佳答案

听起来您想要一个始终以相对于设备 相同的方向绘制其内容的 View ,而不管界面的方向(状态栏等)如何。所以在你的图像中,如果“hello”是用物理音量按钮绘制的“h”,那么你总是希望物理音量按钮绘制“h”,即使用户旋转了设备(以及其余部分) UI 已旋转)。

iOS 通过设置 Root View Controller View 的转换来旋转用户界面。您可以在调试器中检查:

# 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>>

因此,您可以在绘制内容之前通过对图形上下文应用逆变换来撤消此操作。但是您还必须调整图形上下文的原点,这使得它有点棘手。

首先,您需要将原点移动到 View 的中心。然后应用逆变换来撤销界面旋转。然后你把原点移回去。假设您的 CGLayer 与您的 View 大小相同(纵向),这应该可行:

- (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 度的 View ,并将 View 旋转到正确的方向。

我在这里放了一个测试项目:

https://github.com/mayoff/stackoverflow-cglayer-unrotating

在测试项目中,您可以看到一个正常运行的半透明工具栏 - 它会旋转到离地面最近的屏幕边缘。在那下面是使用上面的 drawRect: 方法来补偿用户界面旋转的 View 。

关于objective-c - 如何保持 CGLayerRef 不变,即使在设备方向切换之后也是如此?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9345114/

相关文章:

ios - 双指缩放 UILabel

ios - Xcode 11.4找到无效的调试信息,调试信息将被剥离

ios - 钛给出错误:指定的配置文件无效或类型错误

ios - AutoLayout 的按钮彼此重叠

iphone - 检测何时按下主页按钮 iOS

ios - 从 CCLayer 做 Storyboard segue

iphone - 支持ARC的ios绘图框架

ios - UIButton setImage : forState not working with 64 bit architecture

ios - 登录时从 Twitter 获取数据

ios - UITextField 没有接收到触摸事件