CATiledLayer绘制内容前会先将瓦片清空

13

大家好,

我在使用CATiledLayer时遇到了一些问题。有没有办法在不将其区域首先清空为白色的情况下触发瓦片重绘? 我已经从CATiledLayer子类中设置fadeDuration返回0。

更具体地说,以下是我所看到的情况和我的目标:

  • 我有一个UIScrollView,内容大小很大... 12000x800左右。其内容视图是由CATiledLayer支持的UIView。
  • UIView呈现出许多自定义绘制的线条。
  • 一切都运作正常,但UIView的内容有时会发生更改。 当发生这种情况时,我想尽可能平滑地重新绘制瓦片。 当我在视图上使用setNeedsDisplay时,瓦片被重新绘制,但它们首先被清除成白色,并且在新内容绘制之前有一小段延迟。 我已经从CATiledLayer子类中设置fadeDuration为0。
  • 我想要的行为似乎应该是可能的...当您放大滚动视图并以更高分辨率重新绘制内容时,重新绘制之前没有任何空白;新内容直接绘制在旧内容之上。那就是我想要的。

谢谢,感谢您的建议。

更新:

只是为了跟进 - 我意识到在重绘之前并不是将瓦片清空为白色,而是彻底去除它们;我看到的白色是位于CATiledLayer支持视图下方的视图的颜色。

作为一个快速的修补/解决方法,在UIScrollView下面放置了一个UIImageView,并在触发CATiledLayer支持的视图的重绘之前将其可见部分渲染到UIImageView中并让它显示。 这显着平滑了重新绘制。

如果有更好的解决方案,例如在首次重绘之前防止目标瓦片消失然后被重新绘制,我仍然很想听听您的想法。


请问,“在触发CATiledLayer支持的视图重新绘制之前”是什么时候?是在drawLayer:inContext:方法中吗? - Yeung
5个回答

4

我发现如果将levelsOfDetailBias和levelsOfDetail都设置为相同的值(例如我的情况是2),那么它只会重绘被setNeedsDisplayInRect:调用触碰的瓷砖,就像你所希望的那样。

然而,如果levelsOfDetail不同于LODB,则对setNeedsDisplayInRect:的任何调用都会重新绘制所有瓷砖。


不,问题不是重绘哪些图块的问题。问题在于如果需要重新绘制一个图块,该图块首先被清除为白色,然后再绘制新内容。我们想要的是在新内容到达之前,图块可以显示缩放的旧内容,而不是仅显示白色。 - Yeung
@Chris,这也帮了我很多,但你知道这种行为的原因吗? - Azat
1
@Azat 这只是我作为iOS开发人员遇到的(长)错误列表中的另一个不幸 :) - Chris
我在Xcode 7.3.1中发现了setNeedsDisplayInRect()的问题,但遗憾的是即使设置匹配4/4或2/2,它仍然会重新渲染所有瓷砖。 - Tom K

1

另一个潜在的选择是使用相同的委托将内容绘制到位图上下文中,并在刷新内容后将位图交换到后备存储器中。这应该会产生无闪烁的结果。话虽如此,我无法告诉您如何完成此操作,而CATiledLayers的一个好处是它们在缩放时自动生成瓷砖,在缩放后平移时预生成瓷砖。

我想看看您如何实现您的应用程序。我已经寻找了几周,以找到一个使用UIScrollView和具有大量自定义绘制线条的CATiledLayer-back视图的示例。苹果有一些很棒的示例代码 - 但它们都涉及图像而不是线条艺术,所以对我没有帮助。


1

你可以在现有的瓦片图层后面添加另一层(可能是CATiledLayer)。这是一种双缓冲解决方案。你可以从一个定时器中调用setNeedsDisplay:来刷新第二个图层,以确保该图层不会与前面的图层同时重绘。


如果CATiles不可见(在某物后面或屏幕外),它们将不会绘制。 - Luke Mcneice

0

我在iPad上遇到了同样的问题。

解决方案比我想象的要简单得多,也比使用UIImageView在重新绘制之前呈现显示要简单得多... :

只需不为图层设置任何背景颜色即可!

我以类似的方式设置了CATiledLayer:

layer = [[CATiledLayer alloc] init];
layer.masksToBounds = YES;
layer.contentsGravity = kCAGravityLeft;

//layer.backgroundColor = [[UIColor whiteColor] CGColor];

layer.tileSize = CGSizeMake(1004.0, 1004.0);
layer.levelsOfDetail = 16;
layer.levelsOfDetailBias = 8;

请注意,我已经将设置图层背景颜色为白色的行注释掉了。之后重新绘制前的白色空白问题消失了!如果有人尝试过,请告诉我。

这对我没有用,去掉背景颜色对瓷砖在重新绘制前的消失毫无影响。 - Abhi Beckert

0

在阅读这些答案并未找到解决方案后,我发现瓷砖化页面是主要的后台任务。
将我的低分辨率占位图像准备在高优先级队列上解决了这个问题-这些图像现在出现在瓷砖化正在进行的同时。缓存占位符图像进一步改善它们的外观 - 它们出现在瓷砖化开始之前。
对于新设备,瓷砖化速度很快,这些技巧可能并不重要。一个由大型扫描图像(例如扫描书籍)组成的示例PDF在我的经验中瓷砖化速度最慢,是很好的测试数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接