我什么时候需要设置CALayer的contentsScale属性?

And*_*rea 31 macos objective-c calayer ios

文档中, Apple声明在以下情况下需要考虑图层的比例因子:

  • 创建具有不同比例因子的其他Core Animation图层,并将它们组合成自己的内容
  • 直接设置Core Animation图层的contents属性

最后的陈述对我来说并不完全清楚.他们还说:

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

小规模还是永远?这仅适用于视图的托管后备层或我添加为后备层的子层的每个层?因为他们也说:

如果应用程序创建没有关联视图的图层,则每个新图层对象的比例因子最初都设置为1.0.如果不更改该比例因子,并且随后在高分辨率屏幕上绘制图层,则会自动缩放图层的内容以补偿比例因子的差异.如果您不希望缩放内容,可以将图层的比例因子更改为2.0,但如果您这样做而不提供高分辨率内容,则现有内容可能会显得比您预期的要小.要解决该问题,您需要为图层提供更高分辨率的内容.


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

Core Animation的合成引擎查看每个图层的contentsScale属性,以确定在合成期间是否需要缩放该图层的内容.如果应用程序创建没有关联视图的图层,则每个新图层对象的比例因子最初都设置为1.0.如果不更改该比例因子,并且随后在高分辨率屏幕上绘制图层,则会自动缩放图层的内容以补偿比例因子的差异.如果您不希望缩放内容,可以将图层的比例因子更改为2.0,但如果您这样做而不提供高分辨率内容,则现有内容可能会显得比您预期的要小.要解决该问题,您需要为图层提供更高分辨率的内容.

这究竟意味着什么?当我做这样的事情时,layer.contents = (id)image.CGImage我需要设置contentsScale.
当我的图层绘制调用委托方法的内容drawLayer:inContext:并且图层不是视图的背景层时,是否还需要设置它 ?

小智 16

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

小规模还是永远?这仅适用于视图的托管后备层或我添加为后备层的子层的每个层?

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

这样您就可以在10x10概念空间中进行绘图,但如果像素加倍,则后备存储会加倍.

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

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

这究竟意味着什么?当我做类似layer.contents =(id)image.CGImage的事情时,我需要设置contentsScale.

是.但文档中的这段话告诉你的是,如果你不想看起来很难看,内容尺度为2的10pt x 10pt图层需要20px x 20px图像的内容.即,如果要避免缩放工件,则需要在直接设置图层内容时注意图层的contentsScale.

我还需要在我的图层绘制它的内容时调用委托方法drawLayer:inContext:并且该图层不是视图的背衬层吗?

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


Aus*_*tin 6

虽然图层几乎总是在视图中使用,但该图层可能是临时创建的,并添加为视图图层的子图层,或者指定为另一个图层的蒙版.在这两种情况下,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;
Run Code Online (Sandbox Code Playgroud)

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

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   
Run Code Online (Sandbox Code Playgroud)

这对于Retina设备尤其重要,它具有2.0的原生屏幕比例; 默认比例为1.0的图层将显示明显的像素化.


Jan*_*nX2 5

在OS X你基本上

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

我知道在SO上引用外部URL是不好意思,但很难描述这一点.以下是一些在比例因子方面适用于我的代码:

https://github.com/JanX2/ScrollingAboutWindow

希望有所帮助.