Ios 在非全屏和全屏UIViewController之间进行出色的幻灯片切换
我有一个不是全屏的视图控制器(有一个状态栏),我想展示一个全屏的模态视图控制器 如果我在动画开始时隐藏状态栏(父视图将消失或模态视图将出现),那么在一段时间内,父视图将在没有状态栏的情况下可见,看起来像一个bug 如果我在动画结束时执行此操作(父视图的ViewDidEnglishe或模态视图的ViewDidDisplay),则状态栏将在模态视图上显示一段时间,即它不会显示为模态视图“covered it” 有什么方法可以很好地做到这一点吗 编辑:Ios 在非全屏和全屏UIViewController之间进行出色的幻灯片切换,ios,uiviewcontroller,Ios,Uiviewcontroller,我有一个不是全屏的视图控制器(有一个状态栏),我想展示一个全屏的模态视图控制器 如果我在动画开始时隐藏状态栏(父视图将消失或模态视图将出现),那么在一段时间内,父视图将在没有状态栏的情况下可见,看起来像一个bug 如果我在动画结束时执行此操作(父视图的ViewDidEnglishe或模态视图的ViewDidDisplay),则状态栏将在模态视图上显示一段时间,即它不会显示为模态视图“covered it” 有什么方法可以很好地做到这一点吗 编辑: 一种可能是创建一个windowLevel=ale
一种可能是创建一个windowLevel=alert的UIWindow,至少在动画持续时间内。示例iAd广告似乎很好地覆盖了状态栏,没有另一个窗口,因此它一定是可能的。我在我的应用程序中使用以下代码:
[[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。这里有一个似乎有效的解决方案。您可以从我的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];
}
从另一个视图控制器使用它,如下所示:
@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];
}
可能有点麻烦,但您是否考虑过:
UIImage
的initWithFrame
)不适用于此,因为您无法拍摄状态栏的屏幕截图。另一个有趣的小项目。这是我能想到的最好的了。如果您不介意使用自己的容器控制器来管理显示/取消显示视图控制器,这也不算太糟糕。我试着用一种通用的方式做一些事情,但如果需要的话,可以将其应用到带有ContainerViewController的应用程序中 请注意,我只实现了相当于
uimodaltransationstylecoververtical
。您也可以根据自己的喜好自定义动画
相关动画代码:
- (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];
}];
}
-(无效)presentViewController:(UIViewController*)viewControllerToPresent
{
//如果没有控制器,则不执行任何操作
如果(!viewControllerToPresent)返回;
[\uu viewcontrolleraddobject:viewControllerToPresent];
CGRect toFrame=viewControllerToPresent.view.frame;
toFrame.origin=CGPointMake(0,CGRectGetMaxY(self.view.bounds));
viewControllerToPresent.view.frame=toFrame;
[UIView转换WithView:self.view
持续时间:0.2
选项:UIViewAnimationOptionTransitionNone
动画:^{
[[UIApplication sharedApplication]setStatusBarHidden:viewControllerToPresent.wantFullScreenLayout with Animation:UIStatusBarAnimationSlide];
[self.view addSubview:viewControllerToPresent.view];
viewControllerToPresent.view.frame=[UIScreen Main Screen].applicationFrame;
}
完成:无];
}
-(无效)解雇ViewController
{
//如果显示第一个控制器,则无需关闭
如果(_viewControllers.count,可以使用performSelector:withDelay:
告诉状态栏设置动画,然后以正确的延迟启动模态控制器,使其与状态栏动画一致。Gabriel,但如果我理解正确,这是一个淡入淡出,而不是幻灯片动画。也许我应该更具体一些。好的,现在我明白你想要什么了。你希望模态视图与stan一起出现吗从底部添加动画并覆盖状态栏。但我认为这是不可能的,因为状态栏是用于应用程序的,而不是用于视图。因此,正如在我的代码中一样,您最多可以在同一动画中隐藏状态栏。然后,当模式视图出现时,状态栏隐藏动画。我已经在关于UIWindow方法的问题中写道,但我不想使用它,因为在状态栏或警报级别上有一个窗口还有很多其他问题。我已经检查过iAd不使用其他窗口。所以你的新要求是不要使用位于状态栏上方的窗口。在我花时间找出解决方案之前知道这一点会很好。汤姆,我已经补充了这一点在回答前2天。您无法对状态栏进行截图。UIGetScreenImage()过去是这样做的,但你不能再这样做了。状态栏是它自己的窗口,你无法获得它的引用,好吧。我认为你的UIWindow解决方案可能是正确的选择。当我们需要在视图控制器之间进行不寻常的转换时,我们在应用程序中使用类似的技术。