【问题标题】:When do I need to set the contentsScale property of a CALayer?什么时候需要设置 CALayer 的 contentsScale 属性?
【发布时间】:2013-08-29 19:48:26
【问题描述】:

documentationApple 声明中,您需要考虑图层的比例因子:

  • 创建具有不同比例因子的附加核心动画层,并将它们合成到自己的内容中
  • 直接设置核心动画层的内容属性

最后一个陈述对我来说并不完全清楚。 他们还说:

直接使用 Core Animation 层来提供的应用程序 内容可能需要调整其绘图代码以考虑比例 因素。通常,当您在视图的 drawRect: 方法中绘制时,或者 在 drawLayer:inContext: 层的委托方法中,系统 自动调整图形上下文以考虑比例 因素。

通常还是总是?这仅对视图的托管支持层或我作为子层添加到支持层的每一层有效?因为他们还说:

如果您的应用程序创建没有关联视图的层,则每个 新图层对象的比例因子最初设置为 1.0。如果你不 更改该比例因子,如果您随后在 高分辨率屏幕,图层内容自动缩放 以补偿比例因子的差异。如果你不想 要缩放的内容,您可以将图层的比例因子更改为 2.0,但如果您在不提供高分辨率内容的情况下这样做,您现有的内容可能看起来比您预期的要小。修理 这个问题,你需要为你的 层。


我很难想象没有视图的图层,我可以想象图层的层次结构,但是一旦我想显示它们,我应该将其添加为视图支持层的子层次结构,或者确实存在使用它们的其他方法(比如在上下文中创建和渲染)?

Core Animation 的合成引擎查看 contentsScale 每一层的属性判断该层的内容是否 在合成过程中需要缩放。如果您的应用程序创建 没有关联视图的图层,每个新图层对象的比例 因子最初设置为 1.0。如果你不改变那个比例 因素,如果您随后在高分辨率上绘制图层 屏幕,图层的内容会自动缩放以补偿 对于比例因子的差异。如果您不想要内容 要进行缩放,您可以将图层的比例因子更改为 2.0,但如果 你这样做没有提供高分辨率的内容,你现有的 内容可能看起来比您预期的要小。解决这个问题 问题,您需要为您的图层提供更高分辨率的内容。

这实际上是什么意思?当我做类似layer.contents = (id)image.CGImage 的事情时,我需要设置contentsScale。
当我的图层调用委托方法drawLayer:inContext: 并且该图层不是视图的支持层时,我是否还需要设置它?

【问题讨论】:

标签: ios objective-c macos calayer


【解决方案1】:

re: 图层内容通过 -drawRect: 或 -drawLayer:inContext:

通常还是总是?这仅对视图的托管支持层或每一层有效 我作为子层添加到支持层?

总是。当调用这些方法时,当前上下文已经应用了缩放因子。例如,如果您的图层为 10pt x 10pt,则它的边界为 {0,0,10,10},而与 contentsScale 无关。如果 contentsScale = 2(例如你在视网膜上),这实际上是 20x20 像素。 CALayer 已经设置了一个 20x20px 的后备存储并应用了比例因子 CGContextScaleCTM(context, 2, 2)。

这样您就可以在 10x10 的概念空间中以任何一种方式进行绘图,但如果像素加倍,则后备存储会加倍。

我很难想象没有视图的图层,我可以想象一个层次结构 图层,但只要我想显示它们,我就应该将其添加为 视图的支持层,或者确实存在使用它们的其他方式(比如创建和只是 在上下文中渲染)?

您可以创建它们,将它们添加为子图层,并将它们的委托设置为您实现 -drawLayer:inContext: 的对象,或者您可以直接设置图层的内容。在 iOS 上,UIView 是一个相当浅的 CALayer 包装器,因此创建子视图而不是直接创建子层通常是有意义的,这就是您不太熟悉这种用法的原因。在 OS X 上,支持层的 NSView 是一个大而复杂的 CALayer 包装器,因此在单个视图中创建整个层的层次结构更有意义。

这实际上是什么意思?当我做类似 layer.contents = (id)image.CGImage 我需要设置contentsScale。

是的。但是文档中的这段话告诉你的是,如果你不想看起来难看,一个 10pt x 10pt 的图层,其 contentsScale 为 2,需要一个 20px x 20px 图像的内容。 IE。直接设置图层内容时,需要注意图层的contentsScale,避免缩放伪影。

当我的图层绘制它的内容时,我是否也需要设置它调用委托方法 drawLayer:inContext: 并且该层不是视图的支持层?

是的。如果您自己创建图层(不是通过 UIView 创建的),则需要手动设置它们的比例。通常这只是 layer.contentsScale = [[UIScreen mainScreen] scale]。 (同样,在 OS X 上这有点复杂,因为屏幕可以在运行时来来去去。)

【讨论】:

  • 感谢您的详细解答!如果A和B都是Z层的子层,Z层是否也需要设置contentsScale,还是父层的contentsScale无关?
【解决方案2】:

在 OS X 上你基本上是

  1. 抓住你窗口的-backingScaleFactor
  2. 将每个 (!) 层的 -contentsScale 设置为该比例因子
  3. 在控制器中实现-layer:shouldInheritContentsScale:fromWindow:
  4. 将每一层的-delegate 设置为该控制器

我知道在 SO 上仅引用外部 URL 是不受欢迎的,但很难描述这一点。以下是一些关于比例因子对我来说正确的代码:

https://github.com/JanX2/ScrollingAboutWindow

希望对您有所帮助。

【讨论】:

  • 有效的替代解决方案是从viewDidChangeBackingProperties(或windowDid…)设置层(或层)contentsScale
  • 不知道。 AFAIK,这是 Apple 告诉你使用的方式。
【解决方案3】:

虽然图层几乎总是在视图中使用,但该图层可能是临时创建的并添加为视图图层的子图层,或者指定为另一个图层的蒙版。在这两种情况下,都必须设置 contentsScale 属性。例如:

UIView *myMaskedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
CALayer *myMaskLayer = [CALayer new];
myMaskLayer.frame = myMaskedView.bounds;
UIImage *maskImage = [UIImage imageNamed:@"some_image"];
myMaskLayer.contents = (id)maskImage.CGImage;
myMaskLayer.contentsScale = maskImage.scale;
myMaskedView.layer.mask = myMaskLayer;

您可能还想为执行动画构建层的层次结构,而不是使用每个层来支持视图:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];

CALayer *sublayerA = [CALayer new];
sublayerA.contentsScale = myView.layer.contentsScale;
[myView.layer addSublayer:sublayerA];

CALayer *sublayerB = [CALayer new];
sublayerB.contentsScale = myView.layer.contentsScale;
[myView.layer addSublayer:sublayerB];

// Continue adding layers   

这对于原生屏幕比例为 2.0 的 Retina 设备尤其重要;默认比例为 1.0 的图层会显示明显的像素化。

【讨论】:

  • 啊哈!这不适用于自己创建的层解释了为什么我的 Mac 应用程序的托管层没有正确设置 contentsScale。我认为如果我的视图是基于层而不是层托管的,那么它会在创建层时由视图(在 NSView 级别)为我设置。
  • 我认为这个答案和评论解决了我在阅读这个问题时遇到的问题:当您创建一个图层然后将其添加到附加到视图的图层层次结构中时,添加图层本身不会将 contentScale 属性设置为屏幕的属性,对吗?
  • 没错。向视图层次结构添加层不会设置其contentsScale
  • 如果A和B都是Z层的子层,Z层是否也需要设置contentsScale,还是父层的contentsScale无关?
  • 是的! 'sublayerA.contentsScale = myView.layer.contentsScale;'绝对是最好、最优雅的解决方案。用一条线,我的图层从模糊和模糊变为清晰和凉爽。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-25
  • 2011-07-12
相关资源
最近更新 更多