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

时间:2013-08-27 07:05:43

标签: ios objective-c macos calayer

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

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

最后一句话对我来说并不完全清楚。 他们还说:

  

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

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

  

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


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

  

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

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

3 个答案:

答案 0 :(得分:15)

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

  

Normallly还是永远?这仅适用于视图的托管后备层或每个层   我作为子层添加到背衬层?

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

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

  

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

您可以创建它们,将它们添加为子图层,并将它们的委托设置为您实现-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上,这有点复杂,因为屏幕可以在运行时进出。)

答案 1 :(得分: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;

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

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   

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

答案 2 :(得分:5)

在OS X上你基本上是

  1. 抓住你的窗口-backingScaleFactor
  2. 将每个(!)图层的-contentsScale设置为该scaleFactor
  3. 在控制器中实施-layer:shouldInheritContentsScale:fromWindow:
  4. 将每个图层的-delegate设置为该控制器
  5. 我知道在SO上引用外部URL是不好意思,但很难描述这一点。以下是一些在比例因子方面适用于我的代码:

    https://github.com/JanX2/ScrollingAboutWindow

    希望有所帮助。