【问题标题】:Drawing woes with CALayer使用 CALayer 绘制问题
【发布时间】:2010-11-21 04:48:15
【问题描述】:

首先,我发现 iPhone 在线文档在涉及渲染图层的各种方式时并不十分清楚。我明白了,但我不清楚何时使用哪些方法以及哪些需要将该层添加为子层。

我的项目开始时我加载图像并简单地通过 [image drawAtPoint:] 以及 [image drawInRect:] 将它们绘制到 UIView。这些使用当前的图形上下文可以正常工作。

然后今天我碰巧读到了这个使用图层的概念,这样理论上(隐式地)为我的各种图像设置动画将是一件轻而易举的事!

为了记录,我知道文档说子类化 CALayer 是不必要的,但我就是这样做的。 现在我对渲染图层的不同方式感到非常困惑。

  • 绘制层
  • 显示层
  • 显示
  • drawInContext

现在对于所有这些方法,是否需要设置图层的帧大小? 是否需要在视图的图层中添加图层?

给我可见结果的唯一方法是 drawinContext 方法。但是如果我应用一个隐式动画(例如 image.opacity = 0)什么都不会发生,这让我相信我的层没有正确设置。

请有人让这混乱局面恢复秩序。

【问题讨论】:

    标签: iphone core-animation core-graphics quartz-graphics calayer


    【解决方案1】:

    Core Animation 确实让这种事情变得微不足道。布拉德的建议是正确的。底线是您不需要任何这些方法来简单地渲染图层。为了使图层渲染,请确保您已完成以下操作:

    • 设置内容属性:

      [imageLayer setContents:(id)[[UIImage imageNamed@"image.png"] CGImage]];

    • 将图层的边界设置为您想要的大小。

      [imageLayer setBounds:CGRectMake(0.0f, 0.0f, 50.0f, 50.0f)];

    • 设置要在视图中显示的图层的位置(x,y 位置)。默认锚点是图层的中心。此代码使图层在您的视图中居中。

      [imageLayer setPosition:CGPointMake([view bounds].size.width/2, [view bounds].size.height/2)];

    • 将图层添加到视图的图层:

      [[[self view] layer] addSublayer:imageLayer];

    顺便说一句,如果您愿意,您可以通过调用 -setFrame: 在一种方法中同时设置边界和位置。我更喜欢自己使用这两个调用,因为它对我来说更具可读性,但这取决于你自己的喜好。 如果你不设置图层的边界和位置或框架,那么图层将不会渲染。

    如果您愿意,您可以通过创建额外的图层来绘制路径、形状(请参阅 CAShaperLayer)或其他图像并将它们添加为图像图层的子图层或将它们添加为父图层的子图层并给出它们是一个 zPosition,使它们显示在您的图像层前面。

    现在,如果您想为不透明度设置动画,您可以使用隐式动画,只需按照您描述的方式设置 layer 属性,例如[imageLayer setOpacity:0.0f];这将在 0.25 秒内淡化图层及其所有子图层。

    只是一些额外的想法。

    最好的问候。

    【讨论】:

      【解决方案2】:

      如果您希望各个图层只显示一个图像,那么您根本不需要对它们进行子类化。您应该能够将图像(以 CGImageRef 形式)设置为每一层的 contents 属性。然后该层将处理该图像的绘制。您可以使用其CGImage 只读属性获取 UIImage 的 Core Graphics 图像表示。

      不过,您说得对,-drawInContext: 是在 CALayer 子类中放置更多自定义绘图代码的正确位置。如果不继承 CALayer,您可以通过 -drawLayer:inContext: 委托方法让委托更改图层的绘制行为。

      这在 Apple 的 Core Animation Programming Guide"Providing Layer Content" 部分中有详细描述。

      【讨论】:

      • 我最终做的是子类化(因为我的对象很复杂),我自己设置了委托。所以基本上我使用displayLayer。我需要做的就是调用图层的 setNeedsDisplay。所以现在的问题仍然是drawInContext和drawLayer:inContext的用法。这些是手动调用的,还是通过 SetNeedsDisplay 在内部调用的?现在只是好奇。
      • 这是一个更相关的后续问题:我现在可以使用 drawLayer:(CALayer*)layer 渲染到图层。但是,如果我想更新渲染,比如说图层上的动画帧,如果我使用更新的图像设置图层的内容*,则内容会在屏幕上消失。我是否需要删除图层然后对其进行渲染,然后将其重新添加到渲染树中?如果是这样的话,那就吹吧!
      • 第一个问题:drawInContext: 永远不应该被直接调用,而是由 setNeedsDisplay 间接触发。如果您没有覆盖该方法,我相信它会调用委托以帮助通过 -drawLayer:inContext: 显示内容
      • 对于您的第二个问题:您应该能够通过 contents 属性或 -drawInContext: 更改您想要的有关图层内容的任何内容,而无需将其删除并重新添加到图层层次结构中。你的渲染方法一定有问题。
      猜你喜欢
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多