导航控制器上的透明模态视图
我正在尝试在导航控制器上创build一个透明的模式视图。 有谁知道这是可能的吗?
一个模式视图将覆盖它被推到顶部的视图以及您的导航控制器的导航栏。 但是,如果使用-presentModalViewController:animated:方法,那么一旦animation完成,刚刚覆盖的视图将实际上消失,这使得您的模态视图的任何透明度都是毫无意义的。 (您可以通过在您的根视图控制器中实现-viewWillDisappear:和-viewDidDisappear:方法来validation这一点。
您可以直接将模态视图添加到视图层次结构中,如下所示:
UIView *modalView = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; modalView.opaque = NO; modalView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f]; UILabel *label = [[[UILabel alloc] init] autorelease]; label.text = @"Modal View"; label.textColor = [UIColor whiteColor]; label.backgroundColor = [UIColor clearColor]; label.opaque = NO; [label sizeToFit]; [label setCenter:CGPointMake(modalView.frame.size.width / 2, modalView.frame.size.height / 2)]; [modalView addSubview:label]; [self.view addSubview:modalView];
将modalView作为子视图添加到根视图中并不会覆盖导航栏,但它将覆盖下面的整个视图。 我尝试了用来初始化modalView的框架的起源,但负值导致它不显示。 除了状态栏外,我发现覆盖整个屏幕的最好方法是将modalView添加为窗口本身的子视图:
TransparentModalViewAppDelegate *delegate = (TransparentModalViewAppDelegate *)[UIApplication sharedApplication].delegate; [delegate.window addSubview:modalView];
最简单的方法是使用navigationController的modalPresentationStyle属性(但是你必须自己animation):
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext; [self presentModalViewController:modalViewController animated:NO]; modalViewController.view.alpha = 0; [UIView animateWithDuration:0.5 animations:^{ modalViewController.view.alpha = 1; }];
我通过设置一个“OverlayViewController”来实现这个function,该function位于我的窗口或根视图的所有其他子视图之上。 在您的应用程序委托或根视图控制器中进行设置,并将OverlayViewController设置为单例,以便可以从代码或视图控制器层次结构中的任何位置访问它。 然后,您可以随时调用方法来显示模式视图,显示活动指示符等,并且可能会覆盖任何选项卡栏或导航控制器。
根视图控制器的示例代码:
- (void)viewDidLoad { OverlayViewController *o = [OverlayViewController sharedOverlayViewController]; [self.view addSubview:o.view]; }
您可能用于显示模态视图的示例代码:
[[OverlayViewController sharedOverlayViewController] presentModalViewController:myModalViewController animated:YES];
我没有实际上使用-presentModalViewController:animated:
与我的OverlayViewController,但我期望这将工作得很好。
另请参阅: 您的Objective-C单例是什么样的?
我有这个相同的问题,为了解决scheme是添加模式视图与addSubview和animation的视图层次结构中的变化与UIView的animateWithDuration:延迟:选项:animation:完成:
我添加了一个属性和2个方法到包含其他function的UIViewController(FRRViewController)的子类。 我将很快在gitHub上发布所有的东西,但在那之前你可以看到下面的相关代码。 欲了解更多信息,你可以检查我的博客: 如何显示一个透明的模态视图控制器 。
#pragma mark - Transparent Modal View -(void) presentTransparentModalViewController: (UIViewController *) aViewController animated: (BOOL) isAnimated withAlpha: (CGFloat) anAlpha{ self.transparentModalViewController = aViewController; UIView *view = aViewController.view; view.opaque = NO; view.alpha = anAlpha; [view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { UIView *each = obj; each.opaque = NO; each.alpha = anAlpha; }]; if (isAnimated) { //Animated CGRect mainrect = [[UIScreen mainScreen] bounds]; CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height); [self.view addSubview:view]; view.frame = newRect; [UIView animateWithDuration:0.8 animations:^{ view.frame = mainrect; } completion:^(BOOL finished) { //nop }]; }else{ view.frame = [[UIScreen mainScreen] bounds]; [self.view addSubview:view]; } } -(void) dismissTransparentModalViewControllerAnimated:(BOOL) animated{ if (animated) { CGRect mainrect = [[UIScreen mainScreen] bounds]; CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height); [UIView animateWithDuration:0.8 animations:^{ self.transparentModalViewController.view.frame = newRect; } completion:^(BOOL finished) { [self.transparentModalViewController.view removeFromSuperview]; self.transparentModalViewController = nil; }]; } }
以下是我所做的解决问题的方法 – Google详细信息,但这种方法对我来说非常有效:
- 截取底层视图。 https://devforums.apple.com/message/266836 – 这导致了一个现成的方法,返回当前屏幕的UIView。
- 截图到模态视图(我用了一个属性)
- 呈现模态视图
- 在模式视图控制器的viewDidAppear中,将图像设置为索引0处的UIImageView。通过状态栏的高度调整图像的垂直位置。
- 在模式视图控制器的viewWillDisappear中,再次删除图像
效果是:
- 视图以任何模态视图的方式进行animation – 模态视图的半透明部分滑过现有视图
- 一旦animation停止,背景被设置为屏幕截图 – 这使得它看起来好像旧的视图仍然在下面,即使它不是。
- 一旦模态视图的消失animation开始,图像被删除。 操作系统同时显示旧的导航视图,所以模态视图透明地滑开,并且如你所愿。
我尝试在自己的叠加视图中进行animation制作,但效果不佳。 我没有任何迹象表明坠机事件发生。 而不是追逐这一点,我做了bg视图和工程真的很好。
在模态视图中的代码 – 我想你可以找出其余的,即设置属性modalView.bgImage …
- (void)viewDidAppear:(BOOL)animated { // background // Get status bar frame dimensions CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame]; UIImageView *imageView = [[UIImageView alloc] initWithImage:self.bgImage]; imageView.tag = 5; imageView.center = CGPointMake(imageView.center.x, imageView.center.y - statusBarRect.size.height); [self.view insertSubview:imageView atIndex:0]; } - (void)viewWillDisappear:(BOOL)animated { [[self.view viewWithTag:5] removeFromSuperview]; }
self.modalPresentationStyle = UIModalPresentationCurrentContext; [self presentModalViewController:newview animated:YES];
并确保您将模态视图背景设置为透明,
self.view.background = …. alpha:0.x;
如果将模态视图控制器的modalPresentationStyle设置为:
viewController.modalPresentationStyle = 17;
在后台的视图不会被删除。 (TWTweetComposeViewController使用它)。
尽pipe我没有尝试通过App Store审查
这篇关于显示半透明的“正在加载…”视图的文章可能会给出一些关于如何进行的指导。
是的,你必须手动添加视图,如果你想从底部滑入,或者你也必须自己做animation。
我写了一个类来做到这一点,以及使用该类的半模式dateselect器作为示例。
你可以在这个博客文章中find文档,代码在github上
过去一周我一直在研究这个问题。 我尝试了所有在Google和StackOverflow中find的各种答案和示例。 他们没有一个很好地工作。
作为iOS编程的新手,我不知道叫做UIActionSheet
。 所以,如果你试图做到这一点,以显示button的模式覆盖(如模式询问某人如何分享的东西),只需使用UIActionSheet
。
这是一个显示如何做到这一点的例子的网页 。
我从https://gist.github.com/1279713得到了这个想法;
准备:在模式视图xib(或场景使用故事板),我设置全屏幕背景UIImageView(挂钩与.h文件,并给它一个属性“backgroundImageView”)与0.3 alpha。 我将视图(UIView)背景颜色设置为纯黑色。
想法:然后在模式视图控制器的“viewDidLoad”我捕捉从原始状态的屏幕截图,并将该图像设置为后台UIImageView。 将初始Y点设置为-480,并使用EaseInOutanimation选项,使用0.4秒的时间间隔将其滑动到Y点0。 当我们解雇视图控制器时,只需做相反的事情。
模态视图控制器类的代码
.h文件:
@property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView; - (void) backgroundInitialize; - (void) backgroundAnimateIn; - (void) backgroundAnimateOut;
.m文件:
- (void) backgroundInitialize{ UIGraphicsBeginImageContextWithOptions(((UIViewController *)delegate).view.window.frame.size, YES, 0.0); [((UIViewController *)delegate).view.window.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); backgroundImageView.image=screenshot; } - (void) backgroundAnimateIn{ CGRect backgroundImageViewRect = backgroundImageView.frame; CGRect backgroundImageViewRectTemp = backgroundImageViewRect; backgroundImageViewRectTemp.origin.y=-480; backgroundImageView.frame=backgroundImageViewRectTemp; [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{ backgroundImageView.frame=backgroundImageViewRect; } completion:^(BOOL finished) { }]; } - (void) backgroundAnimateOut{ CGRect backgroundImageViewRect = backgroundImageView.frame; backgroundImageViewRect.origin.y-=480; [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{ backgroundImageView.frame=backgroundImageViewRect; } completion:^(BOOL finished) { }]; }
在viewDidLoad中,只需调用:
[self backgroundInitialize]; [self backgroundAnimateIn];
在任何我们解雇模态视图控制器的地方,我们称之为:
[self backgroundAnimateOut];
请注意,这将永远活动背景图像。 所以如果这个模式视图控制器转换样式(或者segue转换样式)没有被设置为“Cover Vertical”,你可能不需要调用animation方法。
我最终通过结合覆盖视图控制器(参见:pix0r的答案)隐藏/隐藏,然后隐藏或显示基于这个非常好的博客post的视图控制器,完成了这个导航或标签栏界面。
关于视图控制器,提示是使其背景视图为clearColor
,然后半透明叠加视图是可见的,并且视图控制器中的子视图在前面添加任何视图,最重要的是不透明。
我已经创build了开放的soruce库MZFormSheetController来显示额外的UIWindow上的模态表单。 您可以使用它来呈现透明模式视图控制器,甚至可以调整呈现的视图控制器的大小。
对于iOS 8 +,您可以使用UIModalPresentationOverCurrentContext
演示文稿样式呈现视图控制器,以轻松实现所需的行为。
UIViewController *viewController = [[UIViewController alloc] init]; viewController.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.9f]; viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; [self presentViewController:viewController animated:YES completion:nil];
如果你还需要支持iOS 7 – 请检查这个线程 。
您可以通过在视图和导航栏上叠加透明/半透明button来实现透明/半透明模式视图效果。
您可以通过UINavigationController的navigationBar属性访问导航栏。
我发现不像UILabel的UIButton会捕捉鼠标事件 – 因此会给出正确的模态行为。
我刚刚find了一个解决方法。 只需创build一个UIViewController的1X1并将其添加到您的父视图控制器。 并显示该UIViewController中的透明模态视图控制器。
on viewDidLoad;
self.dummyViewController = [[UIViewController alloc] init]; [self.dummyViewController.view setFrame:CGRectMake(0,0,1,1)]; [self.view addSubView:self.dummyViewController.view];
当你需要打开一个透明的ViewController;
[self.dummyViewController presentModalViewController:yourTransparentModalViewController animated:true];
如果你需要像附件一样的屏幕,下面的代码可以帮助你。
代码:
MyViewController * myViewController = [[MyViewController alloc] initWithNibName:nibName bundle:nil]; UINavigationController * myNavigationController = [[UINavigationController alloc] initWithRootViewController: myViewController]; myNavigationController.modalPresentationStyle = UIModalPresentationPageSheet; [self presentModalViewController: myNavigationController animated:YES];
如果说你想要一个覆盖屏幕,使用parentViewController.view,它会放置在导航栏++上方
MyCustomViewController* myOverlayView = [[MyCustomViewController alloc] init]; [self.parentViewController.view addSubview:myOverlayView];
这对我工作:
UIViewController *modalViewController = [[UIViewController alloc] init]; modalViewController.view.backgroundColor = [UIColor whiteColor] colorWithAlpha:0.5]; [self showDetailViewController:modalViewController sender:nil];