UIImageView介绍动画问题

发布于 2024-10-11 08:51:17 字数 936 浏览 2 评论 0原文

我正在尝试为我的 iOS 应用程序创建介绍动画,但遇到了计时问题。我特别想在介绍动画播放后更改屏幕。我目前使用 UIImageView ,但似乎没有办法做到这一点。许多 stackoverflow 问题都说使用 NSTimer 或 PerformSelector:afterDelay 但这些不是准确的计时器,在我的例子中是完全错误的。这就是我正在做的事情。

  1. 将 UILaunchImageFile 设置为 LaunchImage.png
  2. AppDelegate 分配 IntroViewController
  3. IntroViewController.LoadView 分配 IntroView
  4. IntroView.initWithFrame 执行以下操作 UIImageView* iv = iv.animationImages = iv.animationDuration = 2.0 iv.animationRepeatCount = 1 [iv startAnimating]
  5. 设置 NSTimer/performSelector:afterDelay?
  6. 当计时器触发器从 IntroViewController 更改为其他内容时。

如果我执行步骤 5 或 6,它将无法正常工作。它确实正确地播放了动画,并且会正确地更改视图/视图控制器,但时间却非常错误。当您以这种方式调用 startAnimating 时,它实际上可能不会在一两秒内启动动画。我想是因为该应用程序仍在以某种方式加载资源。然而,这个时间在模拟器或所有设备上并不一致。事实上,在同一设备上多次运行可能会产生不同的结果。因此我不能硬编码一些延迟。

我想做的就是检测 UIImageView 动画已播放最后一帧并执行某些操作。就是这样。到目前为止,我发现的最好的解决方案是以某种方式设置一个计时器,然后做一些事情,但在我的情况下,计时器不是一个解决方案。

有什么想法吗?

I am trying to create an intro animation for my iOS app and am having issues with timing. In particular I would like to change screens after the intro animation plays. I currently use a UIImageView and there does not appear to be a way to do this. Many stackoverflow questions say to use an NSTimer or performSelector:afterDelay but these are not accurate timers and in my case are completely wrong. Here is what I am doing.

  1. Set UILaunchImageFile to LaunchImage.png
  2. AppDelegate allocs an IntroViewController
  3. IntroViewController.LoadView allocs IntroView
  4. IntroView.initWithFrame performs the following
    UIImageView* iv =
    iv.animationImages =
    iv.animationDuration = 2.0
    iv.animationRepeatCount = 1
    [iv startAnimating]
  5. Set NSTimer/performSelector:afterDelay?
  6. When timer triggers change from IntroViewController to something else.

If I perform either step 5 or 6 it does not work correctly. It does correctly play the animation and it will correctly change the view/view controller, but the timing is horribly horribly wrong. When you call startAnimating in this manner it may not actually start the animation for a full second or two. I presume because the app is still loading in resources somehow. This time however is not consistent across the simulator or all devices. Infact several runs on the same device may have different results. Thus I can not hard code some delay.

All I want to do is detect that a UIImageView animation has played the last frame and do something. That's it. The best solution I've found so far is to set a timer in some manner and then do something, but in my situation a timer is not a solution.

Any ideas?

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

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

发布评论

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

评论(1

反差帅 2024-10-18 08:51:17

您观察到的长时间延迟是由于读取和解码图像造成的,这是 UIImageView 在动画开始之前执行的操作。

Core Animation 为您执行动画,并在渲染服务器中进行绘制,这是一个单独的进程。请记住,您在屏幕上看到的内容并不一定代表应用程序的图层树的即时图片:核心动画渲染架构

UIImageView 不提供为您提供准确结果的工具。我建议:

  1. 制作一个您自己的 UIView
  2. 使用离散计算模式创建一个 CAKeyframeAnimation 并将图像的 CGImageRefs 作为其值。
  3. 将动画的委托设置为您的 IntroViewController
  4. 将动画添加到“内容”键的视图图层。
  5. 完成后,您的 IntroViewController 将获得animationDidStop:finished:。

不过,需要考虑两件事:

首先,使用电影而不是一系列图像可以获得更好的结果,因为电影可以从存储中流式传输。

其次,更重要的是,该解决方案将改善时序情况,但不会完全缓解它。 animationDidStop:finished: 当您的应用认为动画完成时调用...这不一定是它看起来完成的时间。

如果您不依赖委托回调来进行媒体计时,您会做得更好:相反,添加此动画和转换视图的动画(如有必要,使用CAAnimationGroup)在运行循环的同一轮中。使用第一个动画持续时间的 beginTime 延迟后者。根据您正在执行的操作,您可能还必须设置第二个动画的填充模式才能在第一个动画期间获得正确的行为。

The long delay you observe is due to reading and decoding the images, which UIImageView does before the animation begins.

Core Animation performs the animation for you, and it does its drawing in the render server, which is in a separate process. Remember that what you see on the screen doesn't necessarily represent your app's instantaneous picture of your layer tree: Core Animation Rendering Architecture.

UIImageView doesn't provide facilities to give you accurate results here. I'd suggest:

  1. Make a UIView of your own.
  2. Create a CAKeyframeAnimation with discrete calculation mode and your images' CGImageRefs as its values.
  3. Set the animation's delegate to your IntroViewController.
  4. Add the animation to your view's layer for the "contents" key.
  5. Your IntroViewController will get animationDidStop:finished: when it's done.

Two things to consider, though:

First, you'll get better results using a movie rather than a series of images, since the movie can be streamed from storage.

Second, and more importantly, this solution will improve the timing situation but will not totally mitigate it. animationDidStop:finished: is called when your app thinks the animation is done… which is not necessarily exactly when it appears to finish.

You'll do better if you don't rely on delegate callbacks for media timing: instead, add this animation and the animation transitioning your views (using a CAAnimationGroup if necessary) in the same turn of the run loop. Delay the latter with a beginTime of the first animation's duration. Depending on what you're doing, you may have to set the second animation's fill mode as well to get the correct behavior during the first.

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