iPhone SDK - 动画子视图

4
我有一个视图,其中包含一个UIWebView和一个OptionsPane(自定义UIViewController与自定义视图)。
我希望当显示该视图时,选项窗格(位于主视图的顶部)能够翻转到正确位置。我正在使用代码,但是得到了奇怪的结果。
第一次显示视图时,选项窗格似乎已经可见...当我在我的navController上点击“返回”并再次打开视图时,动画效果完美。
有人可以对这个话题进行解释吗?
- (void)viewDidLoad {
    [super viewDidLoad];
    optionsPane=[[OptionsPaneController alloc] initWithNibName:@"OptionsPane" bundle:nil];
}

- (void)viewWillAppear:(BOOL)animated {

    [optionsPane.view removeFromSuperview];
    [self checkOptionsVisible];
}

-(void)checkOptionsVisible{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.5]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[optionsPane view] cache:YES];
    [[self view] addSubview:[optionsPane view]];
    [theWebView setFrame:CGRectMake(0,87,320,230)];
    [[optionsPane view] setFrame:CGRectMake(0,0,320,87)];
    [UIView commitAnimations];      
}

请注意编辑者。除非问题中的文本对问题至关重要,否则请不要更改发帖者发布的实际问题文本。通过编辑我的文本,您实际上更改了问题。请保留您的标签,恢复原来的语言。 - Dutchie432
4个回答

1

嗯,我认为第一次不会发送viewWillAppear消息。在SDK中有两件事情需要注意。你应该在这个消息中调用super,并且有一个大警告可能适用于第一次:

警告:如果视图控制器的视图直接添加到视图层次结构中,则视图控制器将不会收到此消息。如果您插入或添加一个具有视图控制器的视图到视图层次结构中,则应直接向相关联的视图控制器发送此消息。未发送此消息将防止显示任何关联动画。

最终,我建议通过调试器运行并确保viewWillAppear消息在您认为的时间被发送。


非常有趣...我可能错过了那个注释。让我稍微试试,然后告诉你故事是什么,因为我相信它正在被调用。 - Dutchie432
第一次它能够正常触发,而且所有后续的触发也都没问题。 - Dutchie432
糟糕,我原本希望那会有所帮助。 - Boiler Bill

0

根据您的情况更新:

改为拥有四个视图:

  1. 一个后备视图

  2. 主视图

  3. 后视图(选项窗格)100像素

  4. 前视图(空白视图)100像素

将主视图正常添加到后备视图中。

在希望出现选项窗格的位置将前视图添加到后备视图中。

确保前视图和后视图具有相同的框架。

使用与下面相同的代码,使用翻转前景和背景视图的方法。


原始答案

你需要三个视图:

  1. 一个背景视图

  2. 前视图

  3. 后视图

背景视图只是保持另外两个视图在翻转过程中的位置。以下是翻转方法,我将它们都放在了背景视图控制器中:

- (void)displayBack{

    //parent controller is an ivar so the sub-view controllers know who their daddy is
    backController.parentController = self;


    [UIView beginAnimations:nil context:@"flipTransitionToBack"];
    [UIView setAnimationDuration:1.2];

    //note self.view IS the backing view
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];

    //remove the front view
    [[frontController view] removeFromSuperview];
    //add the back view view
    [self.view addSubview:[backController view]];
    [UIView commitAnimations];

    //giving a heads up to the view that is about to come on screen
    [backController viewWillAppear:YES];

}



- (void)displayFront{

    [UIView beginAnimations:nil context:@"flipTransitionToFront"];
    [UIView setAnimationDuration:1.2];

    [UIView setAnimationDelegate:self];

    //I'm interested in knowing this has happened
    [UIView setAnimationDidStopSelector:@selector(flipAnimationDidEndWithID:finished:context:)];

    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
    //remove back view
    [[backController view] removeFromSuperview];
    //add the front view
    [self.view addSubview:[frontController view]];
    [UIView commitAnimations];

}  

区别在于,我同时拥有两个视图显示,一个直接位于另一个上方约100像素高的位置 - 我不是在它们之间切换 - 我只是让顶部视图以一种翻转的方式“出现”。 - Dutchie432
嗯...然后只需制作一个空白且高度为100像素的“虚假”前视图。在选项面板和该视图之间进行切换。这应该可以解决你的问题。 - Corey Floyd
我需要在一个独立的项目中尝试这个,然后再去“撕毁”我的当前代码来看看它是否有效。我会及时告诉你结果。 - Dutchie432
祝你好运。为了鼓励你,这段代码片段在生产项目中绝对可以正常工作。当你测试它时,你会发现它是否能够与部分子视图一起工作。 - Corey Floyd
我真的不确定我需要做所有这些... 在准备实现这段代码之后,我发现这段代码确实在两个 UIView 之间转换... 我正在尝试将一个 UIView 显示为另一个 UIView 上的对象,如果可以的话... 如果我遗漏了什么,请告诉我... - Dutchie432

0

如果我理解你的解释正确的话,我前几天也遇到了一个非常类似的问题。

在第一次加载时发生的情况是,viewDidLoad首先触发。加载nib文件需要比viewWillAppear自己触发所需的时间更长一些。

我们得到的是,在viewWillApper已经退役后,nib才会加载。

在此之后的任何加载中,viewDidLoad都不会触发,让viewWillAppear执行其忠实的翻转工作。

怎么办?
首先,尝试更改代码以使用“viewDidAppear”。这应该有所帮助,但您必须查看它是否看起来不错。

另一个选择(丑陋的选择,我知道)是在viewDidLoad上调用checkOptionsVisible。
如果这些都没有帮助,我会考虑使用计时器作为hack - 如果要求允许的话。

我希望这使您更接近解决问题。


有趣的是...将函数调用移动到viewDidAppear会导致一些非常奇怪的效果,而不是我想要的...我需要尝试一下计时器选项并回来告诉你。谢谢! - Dutchie432
感谢您将其注释掉。我期待着听到您的工作经验(也许最终对我也有帮助 :) )。 - David Salzer

0

UIViewController上的视图属性是惰性加载的——即使您正在使用nib进行初始化,视图本身直到第一次访问该属性时才会实例化。

如果您在viewDidLoad中访问optionsPane.view(您不需要对其执行任何操作,只需访问该属性以强制加载),则可能会获得所需的结果,但没有看到更多代码很难确定发生了什么。


我尝试在设置optionsPane = [[optionsPane alloc] init];之后立即执行类似NSLog(@“%d”,optionsPane.view.bounds.size.height)的操作;这些调用发生在将optionsPane视图添加为子视图之前。但仍然没有成功。我开始想知道是否应该放弃动画 - 它确实是非必要的。 - Dutchie432
好的,那个想法就这样吧... 这里有一个新想法:第二次经过时唯一不同的是[optionsPane.view removeFromSuperview]实际上正在做某事。您尝试在viewDidLoad中将optionsPane.view添加到self.view中了吗?可能是无操作的removeFromSuperview以某种方式阻止动画系统识别随后的addSubview是可动画的。 - Skirwan
我确实相信我之前尝试过那个。我再次实现了那行代码,但是没有任何可见的变化...非常感谢你的努力! - Dutchie432
这里有一条奇怪的信息。如果在viewDidLoad中设置[[optionsPane view] setFrame:CGRectMake(0,0,0,0)]; - 则从(0,0,0,0)到checkOptionsVisible中指定的(0,0,320,87)的更改动画会显示出来。那么,为什么会出现那个动画,而不是“问题”动画呢? - Dutchie432
哦,而在第二次运行时,调整大小动画不显示,而“问题”动画则会显示。 - Dutchie432

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