非全屏和全屏UIViewController之间的良好幻灯片转换

时间:2011-12-11 12:45:38

标签: ios uiviewcontroller

我有一个不是全屏的视图控制器(有一个状态栏),并且想要一个全屏的模态视图控制器。

如果我隐藏动画开头的状态栏(父视图的viewWillDisappear或模态的viewWillAppear),那么在没有状态栏的情况下,父视图将会显示,看起来像一个错误。

如果我在动画结束时(父视图的viewDidDisappear或模态的viewDidAppear)执行此操作,则状态栏将在模态视图上显示片刻,即它不会显示为模态视图“覆盖它”。

有没有办法很好地做到这一点?

编辑:

一种可能性是至少在动画持续时间内使用windowLevel = alert创建UIWindow。如果没有其他窗口,示例iAd广告似乎很好地覆盖状态栏,因此必须以某种方式实现。

4 个答案:

答案 0 :(得分:4)

另一个有趣的小项目。这是我能想到的最好的。如果您不介意使用自己的容器控制器来管理呈现/解除视图控制器,那也不算太糟糕。我尝试以一般方式做事情,但如果需要,可以将其转换为带有ContainerViewController的应用程序。

请注意,我只实现了UIModalTransitionStyleCoverVertical的等效内容。您也可以自定义动画。

相关动画代码:

- (void)presentViewController:(UIViewController *)viewControllerToPresent
{   
    // do nothing if no controller
    if (!viewControllerToPresent) return;

    [__viewControllers addObject:viewControllerToPresent];
    CGRect toFrame = viewControllerToPresent.view.frame;
    toFrame.origin = CGPointMake(0, CGRectGetMaxY(self.view.bounds));
    viewControllerToPresent.view.frame = toFrame;

    [UIView transitionWithView:self.view
                      duration:0.2
                       options:UIViewAnimationOptionTransitionNone
                    animations:^{
                        [[UIApplication sharedApplication] setStatusBarHidden:viewControllerToPresent.wantsFullScreenLayout withAnimation:UIStatusBarAnimationSlide];
                        [self.view addSubview:viewControllerToPresent.view];
                        viewControllerToPresent.view.frame = [UIScreen mainScreen].applicationFrame;
                    }
                    completion:nil];
}

- (void)dismissViewController
{
    // nothing to dismiss if showing first controller
    if (__viewControllers.count <= 1) return;

    UIViewController *currentViewController = [__viewControllers lastObject];
    UIViewController *previousViewController = [__viewControllers objectAtIndex:__viewControllers.count - 2];

    [UIView transitionWithView:self.view
                      duration:0.2
                       options:UIViewAnimationOptionTransitionNone
                    animations:^{
                        [[UIApplication sharedApplication] setStatusBarHidden:previousViewController.wantsFullScreenLayout withAnimation:UIStatusBarAnimationSlide];
                        CGRect toFrame = currentViewController.view.frame;
                        toFrame.origin = CGPointMake(0, CGRectGetMaxY(self.view.bounds));
                        currentViewController.view.frame = toFrame;
                    }
                    completion:^(BOOL finished) {
                        [currentViewController.view removeFromSuperview];
                        [__viewControllers removeLastObject];
                    }];
}

答案 1 :(得分:0)

我在我的应用程序中使用此代码执行此操作:

[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation: UIStatusBarAnimationSlide ];


DocumentListViewController * dl = [[DocumentListViewController alloc] initWithNibName:@"DocumentListView" bundle:nil] ;
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:dl];
[dl release];

// Go to the list of documents...
[[self.view superview] addSubview:nav.view];

nav.view.alpha = 0.0 ;

[self hideActivityAlert];

[UIView animateWithDuration:1.0 animations:^{
    nav.view.alpha = 1.0; } completion:^(BOOL A){
        [self.view removeFromSuperview];
        [self release];} ];

动画发生时,状态栏会轻微显示。

当状态栏被隐藏时,您必须确保第一个视图将填充空间。使用具有适当值的属性autoresizingMask。

答案 2 :(得分:0)

这是一个似乎有效的解决方案。您可以从我的TSFullScreenModalViewController派生您想要以模态方式呈现的viewcontroller,或者您可以直接在视图控制器本身中实现代码。

@interface TSFullScreenModalViewController : UIViewController
{
    UIWindow*   _window;
}

- (void) presentFullScreenModal;

@end

@implementation TSFullScreenModalViewController

- (void) viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear: YES];

    [_window resignKeyWindow];
    [_window release];
    _window = nil;
}

- (void) presentFullScreenModal
{
    UIViewController* rvc = [[UIViewController new] autorelease];
    rvc.view.backgroundColor = [UIColor clearColor];

    _window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds] ;
    _window.windowLevel = UIWindowLevelStatusBar+1;
    _window.backgroundColor = [UIColor clearColor];
    _window.rootViewController = rvc;
    [_window makeKeyAndVisible];

    [UIApplication sharedApplication].statusBarHidden = YES;
    [rvc presentModalViewController: self animated: YES];
    [UIApplication sharedApplication].statusBarHidden = NO;
}

@end

导出模态视图控制器,如下所示:

@interface MyModalViewController : TSFullScreenModalViewController
{
}

- (IBAction) onDismiss:(id)sender;

@end

从另一个视图控制器中使用它,如下所示:

- (IBAction) onShowModal:(id)sender
{
    MyModalViewController* mmvc = [[MyModalViewController new] autorelease];
    [mmvc presentFullScreenModal];
}

最后,像往常一样关闭视图控制器:

- (IBAction) onDismiss:(id)sender
{
    [self dismissModalViewControllerAnimated: YES];
}

答案 3 :(得分:0)

可能就像使用performSelector延迟modalViewController的表示一样简单:withDelay:

告诉状态栏动画显示然后以正确的延迟启动模态控制器,使其与状态栏动画一致。