10

我有一个视图控制器,它的视图包含一个UIImageView动画:

//AnimationViewController::ViewDidLoad event:
var ctlAnimations = new UIImageView();

ctlAnimations.AnimationImages = list.ToArray();  //<--list contains the UIImages
ctlAnimations.AnimationDuration = 1.0 * list.Count;
ctlAnimations.StartAnimating();

this.Add(ctlAnimations);

这非常有效:当我推入AnimationViewController导航堆栈时,它会显示UIImage.

但现在我需要显示AnimationViewController自定义动画过渡:

var transition = CATransition.CreateAnimation ();
transition.Duration = 0.3f;
transition.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
transition.Type = CATransition.TransitionFade;
this.View.Layer.AddAnimation (transition, "fade");
//viewController is being pushed with animated=false, because we have a custom animation
base.PushViewController (viewController, false);  
this.View.Layer.RemoveAnimation("fade");

很有效,因为新视图使用指定的自定义动画过渡到位。

但是当我使用动画过渡AnimationViewController推入堆栈时,它会显示但动画不会运行。相反,它显示动画的第一帧(列表中的第一个图像),并且不运行它。

因此,关于过渡的某些事情破坏了在新视图控制器中为 a 设置动画的能力UIImage,但我根本不知道该怎么做。

更新:我注意到如果我点击 NavigationController 的后退按钮,然后离开后退按钮并松开(所以我实际上并没有返回),动画开始播放!

4

7 回答 7

1

PushViewController 的工作方式如下:在当前视图控制器上放置下一个视图控制器,您可以说是推入堆栈。从 Apple 文档中可以清楚地看出,您需要使用动画或不使用动画来推送视图控制器。

解决方法:

  1. 设置下一个视图控制器的视图 x 位置超出屏幕右侧的框架
  2. 假设屏幕宽度为 320,则设置下一个视图的 x 位置为 320。
  3. 将下一个视图作为子视图添加到现有视图。
  4. 现在做你的自定义动画。

另一种解决方法:(虽然开销更大)

  • 以编程方式拍摄当前视图的快照。
  • 添加快照图像作为下一个视图控制器的初始视图。
  • 现在推送没有动画的视图控制器。(用户仍会看到旧视图)
  • 在新视图控制器的 viewDidAppear 中启动您的自定义动画。

[我必须警告你,这种拍摄快照的方法可能会给你在旧设备上带来一点延迟。较新的设备足够快,您不会看到任何滞后]

如果您正在实施任何这些解决方案,请告诉我是否有任何问题。

于 2013-02-25T11:57:31.240 回答
0

尝试将动画位放入 ViewDidAppear 而不是 ViewDidLoad。此外,尝试使用断点和 NSLogs 来跟踪动画之后发生的情况,从 ViewDidLoad 和 ViewDidAppear 开始。尝试让动画永远重复,这样你就可以看到它是否曾经动画过。

于 2013-02-23T22:12:14.930 回答
0

我很好奇这里的罪魁祸首是什么。为什么在某些情况下动画无法正确显示?

我的理论是您将动画代码放在 viewWillAppear 而不是 viewDidAppear 中。动画代码在 WILL 或 SHOULD 方法中无法正常运行。

能否请您回复导致问题的原因?

于 2013-02-27T17:57:16.023 回答
0

怀疑#1

我打赌你的代码没有被调用,因为它在 ViewDidLoad 中。我相信您正在创建一个自定义视图堆栈,这意味着您需要使用 Cocoa 中的ChildViewController方法。

我不熟悉 MonoTouch(我只写纯 CocoaTouch),所以这可能不是 100% 正确

我会安慰你的 viewDidLoad 和 viewDidAppear 方法,并绝对确保它们被调用。我怀疑 viewDidLoad 不是。这导致无法在 UIImageView 上调用 viewDidLoad。

在您的代码中,您可能需要相当于(来自objective-c):

[self addChildViewController:viewController];
// OR?
[base addChildViewController:viewController];

这告诉'父'viewController Child 已经可见,所以在适当的时候调用viewDidLoad/Appear 和Unload/Disappear 方法。这在 MonoTouch 中可能不存在,或者 Push 方法可能没有完全实现,因此您可能需要做一些 hacky()的事情,例如手动调用 viewDidLoad 方法。

怀疑#2

也可能是您的“列表”变量(保存图像的变量)为零。如果发生这种情况,动画将不会运行。或者它可能与动画的持续时间有关,尝试将其设置为使其永远重复的任何内容。确保它没有以某种方式运行真正快速,而你只是错过了它。

开始哲学思考
要么开始学习实际的 Cocoa 开发 :) 不意味着火焰,但绝对意味着认真,你会遇到尝试通过翻译层开发应用程序的问题(自定义语言桥旨在绕过编写基础框架/应用程序/平台的语言)。

Titanium/MonoTouch/PhoneGap 永远不会像真正的 Objective-C 那样产生健壮或高质量的应用程序。除此之外,一旦你学习了 Cocoa,它会改变你写其他东西的方式,我怀疑你会想回去。正如同名精彩网站所说,“可可是我的女朋友”

于 2013-02-27T20:52:25.107 回答
0

让我来谈谈IOS中的UI。在 IOS 中,对 UI 元素的访问仅限于单个线程。

除非您正在运行动画,否则单线程将始终是 mainThread。

因此,当您在同一实例中执行多个动画时,您必须使用

  1. 开始动画。

  2. setFrame(或)一些改变 UI 元素状态的方法。

  3. 对您计划制作动画的所有对象重复第 2 步。

  4. commitAnimations 一次执行所有动画。(使用提交动画确保所有动画都在同一个线程上执行)

所以,我想这就是你的情况。

  1. Viewcontroller 启动了一个动画来将视图控制器推入堆栈。

  2. 图像视图在完成第一个动画之前开始另一个动画。

查看链接以获得清晰的想法link1link2

好吧,让我们进入解决方案

将名为 ctlAnimations 的 ivar 和保留属性添加到您的类

在 ViewDidLoad(或)ViewDidAppear

self.ctlAnimations = new UIImageView();
ctlAnimations.image=(UIImage*)[list.toArray() objectAtIndex:0];
this.Add(ctlAnimations);
[self performSelector:@selector(startAnimatingImage) afterDelay:0.1];

使用以下代码创建一个名为 startAnimatingImage 的私有方法

self.ctlAnimations.AnimationImages = list.ToArray();
ctlAnimations.AnimationDuration = 1.0 * list.Count;
ctlAnimations.StartAnimating();

简而言之,我们只是在第一个动画发生时显示了第一张图像,然后我们将动画开始延迟 1 秒,以便它在第一个动画之后执行,然后开始为图像制作动画。

来吧,试一试

于 2013-04-16T05:51:12.760 回答
0

有主线程的概念。所以 UIAnimation 实际上是在主线程上工作的,同时可能会发生另一个任务在同一个主线程上执行的情况。所以这种情况就像 IOS 会根据每个进程的进程 ID 一次给予优先权,对于您需要为相同操作创建后台线程的解决方案。

于 2013-04-25T06:02:29.313 回答
0

好吧,我从来没有弄清楚问题出在哪里,但事实证明存在某种内存泄漏,UIImage以至于在某些手机上我的代码崩溃了。

所以我重写了它来手动做动画。现在我设置了一个计时器并保留了一个帧索引变量,每次计时器响起时,我都会自己更改图像。这相当于同一件事,事实证明它解决了这个问题。

于 2013-05-20T17:49:53.523 回答