动画 UIView 帧更改会导致重新渲染之前先前内容短暂闪烁

发布于 2024-09-14 20:19:27 字数 868 浏览 5 评论 0原文

我有几个具有 CATiledLayer 图层类的 UIViews,因为它们需要使用 UIScrollViews 进行缩放。我使用 Quartz 在 UIViews 中渲染一些 PDF 页面。一切都很好,直到我尝试在页面旋转时对所述视图框架进行动画处理。

动画很好,视图的内容可以快速且廉价地缩放以匹配新的帧大小。动画结束后,我调用 setNeedsDisplay 来重新渲染整个内容。现在,在调用我的 -(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx 之前(但在 setNeedsDisplay 之后),视图内容很快就会恢复到之前的状态状态(在内容变得小于视图的情况下,剩余像素被拉伸边缘像素)。由于新的“渲染通道”,这会导致在恢复正常之前出现一些非常烦人的图形失真。

经过大量调试后,我设法弄清楚这肯定发生在实际绘图周期(而不是我执行 setNeedsDisplay 的应用程序运行周期)期间,但在 -(void)drawLayer 之前:(CALayer*)layer inContext:(CGContextRef)ctx 甚至被调用。

避免或进一步调试这个问题的最明智的方法是什么?

编辑:我整理了一个非常简单的项目,完美地演示了这种效果。 http://dl.dropbox.com/u/1478968/EEBug.zip PS:渲染代码中有一个sleep(2)只是为了在屏幕上更好地观察效果。

I've got several UIViews that have a layer class of CATiledLayer because they need to be zoomed using UIScrollViews. I use Quartz to render some PDF pages inside said UIViews. Everything is fine until I try to animate said views frames on page rotation.

The animation is fine, the contents of the view gets scaled quickly and cheaply to match the new frame size. After the animation I call setNeedsDisplay to re-render the whole thing. Now before my -(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx get's called (but after setNeedsDisplay) the views contents shortly reverts back to the previous state (with the remaining pixels being stretched edge pixels in cases where the contents becomes smaller than the view). This results in a flash of some very annoying graphical distortion before reverting back to normal thanks to the new "render pass".

After a lot of debugging I've managed to sort out that this definitely happens during the actual drawing cycle (rather than the application run cycle where I do setNeedsDisplay) but before -(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx even gets called.

What's the sanest way of avoiding or further debugging this?

Edit: I've thrown together a very simple project that demonstrates this effect perfectly. http://dl.dropbox.com/u/1478968/EEBug.zip
PS: There's a sleep(2) in the rendering code just so that the effect could be better observed on screen.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

z祗昰~ 2024-09-21 20:19:27

我的猜测是,pdf 渲染是由 CPU 完成的,并且需要相当多的时间来将任何 pdf 渲染从 CPU 内存纹理加载到 GPU 内存中以进行实际显示。因此,您的新 UIView 渲染可能会在所有更新的 pdf 图层像素到达 GPU 之前显示。

您最好的选择可能是在 UIView setNeedsDisplay 之前以新的比例因子将新的 pdf 图像预渲染到另一个离屏 CALayer 中,给它时间上传到 GPU(您可能必须分析/调整最差的总线带宽) (您支持的设备),然后完成视图动画,同时在新旧 CALayers 之间快速切换。

My guess is that pdf rendering is done by the CPU, and takes a fair amount of time to texture load any pdf renderings from CPU memory into the GPU memory for actual display. So your new UIView rendering might be getting displayed before all your updated pdf layer pixels makes it to the GPU.

You best bet may be to pre-render the new pdf images at the new scale factor into another offscreen CALayer before the UIView setNeedsDisplay, give it time to upload to the GPU (you may have to profile/tune for the bus bandwidth of the worse case device you support), and then finish your view animation while quickly flipping between old and new CALayers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文