我正在尝试以模式方式呈现视图控制器,具有透明背景。我的目标是让呈现和呈现的视图控制器视图同时显示。问题是,当呈现动画结束时,呈现视图控制器的视图消失。
- (IBAction)pushModalViewControllerButtonPressed:(id)sender
{
ModalViewController *modalVC = [[ModalViewController alloc] init];
[self presentViewController:modalVC animated:YES completion:nil];
}
我知道我可以将视图添加为子视图,但出于某种原因我想避免使用此解决方案。我怎么能解决它?
答案 0 :(得分:181)
对于那些试图让它在iOS 8中运行的人来说,显示透明模态视图控制器的“Apple认可”方式是在当前 ed modalPresentationStyle >控制器到UIModalPresentationOverCurrentContext
。
这可以在代码中完成,也可以通过在故事板中设置segue的属性来完成。
来自UIViewController文档:
<强> UIModalPresentationOverCurrentContext 强>
仅在内容上显示内容的演示样式 父视图控制器的内容。提出的观点 在演示文稿时,不会从视图层次结构中删除内容 饰面。因此,如果呈现的视图控制器没有填满屏幕 对于不透明的内容,基础内容会显示出来。
在弹出框中呈现视图控制器时,此演示文稿 仅当过渡样式为时才支持样式 UIModalTransitionStyleCoverVertical。试图使用不同的 过渡样式触发异常。但是,您可以使用其他 转换样式(部分卷曲转换除外)如果是父级 视图控制器不在弹出窗口中。
适用于iOS 8.0及更高版本。
https://developer.apple.com/documentation/uikit/uiviewcontroller
来自WWDC 2014的“在iOS 8中查看控制器进展”视频详细介绍了这一点。
注意:
viewDidLoad
中设置此参数不会产生任何影响答案 1 :(得分:96)
在iOS 8.0及更高版本中,可以通过将属性 modalPresentationStyle 设置为 UIModalPresentationOverCurrentContext
来完成。//Set property **definesPresentationContext** YES to avoid presenting over presenting-viewController's navigation bar
self.definesPresentationContext = YES; //self is presenting view controller
presentedController.view.backgroundColor = [YOUR_COLOR with alpha OR clearColor]
presentedController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:presentedController animated:YES completion:nil];
答案 2 :(得分:84)
以下代码仅适用于iPad。
self.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalVC animated:YES];
我会添加一个子视图。
这是一个非常好的讨论。具体看一下评论。不仅仅是答案。
如果我是你,我就不会这样做。我会添加一个子视图并执行它。它似乎让我对事物有了更好的控制。
编辑:
正如Paul Linsay所提到的,因为iOS 8所需要的只是UIModalPresentationOverFullScreen
所呈现的ViewController的modalPresentationStyle。这也包括navigationBar和tabBar按钮。
答案 3 :(得分:42)
此代码适用于iOS6和iOS7下的iPhone:
presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];
在这种情况下,您会错过幻灯片动画。要保留动画,您仍然可以使用以下“非优雅”扩展名:
[presentingVC presentViewController:presentedVC animated:YES completion:^{
[presentedVC dismissViewControllerAnimated:NO completion:^{
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:NO completion:NULL];
}];
}];
如果我们的presentationV位于UINavigationController或UITabbarController内部,则需要使用该控制器作为presentationVC。
此外,在iOS7中,您可以实现应用UIViewControllerTransitioningDelegate
协议的自定义过渡动画。当然,在这种情况下,您可以获得透明背景
@interface ModalViewController : UIViewController <UIViewControllerTransitioningDelegate>
首先,在呈现之前,您必须设置modalPresentationStyle
modalViewController.modalPresentationStyle = UIModalPresentationCustom;
然后你必须实现两个协议方法
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
CustomAnimatedTransitioning *transitioning = [CustomAnimatedTransitioning new];
transitioning.presenting = YES;
return transitioning;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
CustomAnimatedTransitioning * transitioning = [CustomAnimatedTransitioning new];
transitioning.presenting = NO;
return transitioning;
}
最后一件事是在CustomAnimatedTransitioning
类
@interface CustomAnimatedTransitioning : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic) BOOL presenting;
@end
@implementation CurrentContextTransitionAnimator
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.25;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if (self.presenting) {
// custom presenting animation
}
else {
// custom dismissing animation
}
}
答案 4 :(得分:18)
我在XCode 7的Interface Builder中苦苦挣扎,将Presentation Style设置为@VenuGopalTewari建议。在此版本中,segue似乎没有Over Current Context
或Over Full Screen
演示模式。因此,为了使其工作,我将模式设置为Default
:
此外,我将模态呈现的视图控制器的演示模式设置为Over Full Screen
:
答案 5 :(得分:17)
创建一个segue以模态方式呈现并将该segue的Presentation属性设置为当前上下文 它将100%工作
答案 6 :(得分:14)
具有透明背景的PresentViewController - 在iOS 8和iOS 9中
MYViewController *myVC = [self.storyboard instantiateViewControllerWithIdentifier:@"MYViewController"];
myVC.providesPresentationContextTransitionStyle = YES;
myVC.definesPresentationContext = YES;
[myVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[self.navigationController presentViewController:myVC animated:YES completion:nil];
并在MYViewController中设置背景颜色为黑色并降低不透明度
答案 7 :(得分:12)
这有点像hacky方式,但对我来说这个代码有用(iOS 6):
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[self presentViewController:self.signInViewController animated:YES completion:^{
[self.signInViewController dismissViewControllerAnimated:NO completion:^{
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:self.signInViewController animated:NO completion:nil];
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;
}];
}];
此代码也适用于iPhone
答案 8 :(得分:11)
此类别适用于我(ios 7,8和9)
H档
@interface UIViewController (navigation)
- (void) presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
@end
M档
@implementation UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
if(SYSTEM_VERSION_LESS_THAN(@"8.0")) {
[self presentIOS7TransparentController:viewControllerToPresent withCompletion:completion];
}else{
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewControllerToPresent animated:YES completion:completion];
}
}
-(void)presentIOS7TransparentController:(UIViewController *)viewControllerToPresent withCompletion:(void(^)(void))completion
{
UIViewController *presentingVC = self;
UIViewController *root = self;
while (root.parentViewController) {
root = root.parentViewController;
}
UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
root.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
root.modalPresentationStyle = orginalStyle;
}];
}
@end
答案 9 :(得分:6)
我在呈现的视图控制器中的init方法中添加了这三行,并且像魅力一样工作:
self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[self setModalPresentationStyle:UIModalPresentationOverCurrentContext];
编辑(在iOS 9.3上工作):
self.modalPresentationStyle = UIModalPresentationOverFullScreen;
根据文件:
UIModalPresentationOverFullScreen 一种视图演示样式,其中呈现的视图覆盖屏幕。演示文稿完成后,不会从视图层次结构中删除所显示内容下方的视图。因此,如果呈现的视图控制器没有用不透明的内容填充屏幕,则底层内容将显示。
适用于iOS 8.0及更高版本。
答案 10 :(得分:6)
如果您正在使用Storyboard,则可以按照以下步骤操作:
- 添加视图控制器(V2),按照您希望的方式设置UI
醇>
提出V2模式
- 醇>
单击segue。在“属性”检查器中,将“演示文稿”设置为全屏。如果您愿意,可以删除动画
- 选择V2。在“属性”检查器中,将“演示文稿”设置为全屏。检查定义上下文并提供上下文
醇>
- 选择V2的MainView(请检查图像)。将backgroundColor设置为清除颜色
醇>
答案 11 :(得分:5)
使用swift解决这个问题的方法如下:
let vc = MyViewController()
vc.view.backgroundColor = UIColor.clear // or whatever color.
vc.modalPresentationStyle = .overCurrentContent
present(vc, animated: true, completion: nil)
答案 12 :(得分:4)
答案 13 :(得分:3)
我创建了一个对象来处理我称之为&#34;叠加模态&#34;的表示,这意味着它保留了背景的视图,并允许你拥有一个透明背景的模态。 / p>
它有一个简单的方法可以做到这一点:
- (void)presentViewController:(UIViewController *)presentedViewController
fromViewController:(UIViewController *)presentingViewController
{
presentedViewController.modalPresentationStyle = UIModalPresentationCustom;
presentedViewController.transitioningDelegate = self;
presentedViewController.modalPresentationCapturesStatusBarAppearance = YES;
[presentedViewController setNeedsStatusBarAppearanceUpdate];
[presentingViewController presentViewController:presentedViewController
animated:YES
completion:nil];
}
将modalPresentationCapturesStatusBarAppearance
属性设置为YES
并强制状态栏外观更新非常重要,如果您呈现的视图控制器具有不同的preferredStatusBarStyle
。
此对象应具有@property (assign, nonatommic) isPresenting
您希望此对象符合UIViewControllerAnimatedTransitioning
和UIViewControllerTransitioningDelegate
协议并实施以下方法:
- (id)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
self.isPresenting = YES;
return self;
}
- (id)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.isPresenting = NO;
return self;
}
和
- (NSTimeInterval)transitionDuration:(id)transitionContext
{
return 0.25;
}
- (void)animateTransition:(id)transitionContext
{
UIViewController* firstVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController* secondVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView* containerView = [transitionContext containerView];
UIView* firstView = firstVC.view;
UIView* secondView = secondVC.view;
if (self.isPresenting) {
[containerView addSubview:secondView];
secondView.frame = (CGRect){
containerView.frame.origin.x,
containerView.frame.origin.y + containerView.frame.size.height,
containerView.frame.size
};
firstView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
[UIView animateWithDuration:0.25 animations:^{
secondView.frame = containerView.frame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
} else {
[UIView animateWithDuration:0.25 animations:^{
firstView.frame = (CGRect){
containerView.frame.origin.x,
containerView.frame.origin.y + containerView.frame.size.height,
containerView.frame.size
};
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
这是一个模拟默认模态动画的幻灯片底部动画,但你可以随意制作它。
重要的是,呈现视图控制器的视图将保留在后面,让您创建透明效果。
此解决方案适用于iOS 7 +
答案 14 :(得分:3)
执行此操作的一种非常简单的方法(例如,使用Storyboards
)是:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"SomeStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SomeStoryboardViewController"];
// the key for what you're looking to do:
vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
vc.view.alpha = 0.50f;
[self presentViewController:vc animated:YES completion:^{
// great success
}];
这会以UIViewController
模式呈现Storyboard
,但背景为半透明。
答案 15 :(得分:2)
当然应该设置UIModalPresentationCurrentContext,但是设置clearColor的位置也很重要!您无法在viewDidLoad函数中设置背景,无法在视图加载之前像在 root view controller 或要显示的控制器的 init函数中那样设置背景!
actionController.view.backgroundColor = [UIColor clearColor];
[self presentViewController:actionController animated:YES completion:nil];
或
- (instancetype)init {
self = [super initWithNibName:nil bundle:nil];
if(self) {
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self.view setBackgroundColor:[UIColor clearColor]];
}
return self;
}
答案 16 :(得分:2)
要在这里回顾所有好的答案和评论,并在移动到新的ViewController
时仍然有动画,这就是我所做的:(支持iOS 6及更高版本)
如果您使用UINavigationController
\ UITabBarController
这是可行的方法:
SomeViewController *vcThatWillBeDisplayed = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeVC"];
vcThatWillBeDisplayed.view.backgroundColor = [UIColor colorWithRed: 255/255.0 green:255/255.0 blue:255/255.0 alpha:0.50];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:presentedVC animated:YES completion:NULL];
如果你这样做,你将失去modalTransitionStyle
动画。为了解决这个问题,您可以轻松地添加到SomeViewController
课程中:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[UIView animateWithDuration:0.4 animations:^() {self.view.alpha = 1;}
completion:^(BOOL finished){}];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.alpha = 0;
}
答案 17 :(得分:2)
适用于iOS 7-10
if #available(iOS 8.0, *) {
nextVC.modalPresentationStyle = .OverCurrentContext
self.presentViewController(nextVC, animated: true, completion: nil)
} else {
// Fallback on earlier version
self.modalPresentationStyle = .Custom
nextVC.modalTransitionStyle = .CrossDissolve
self.presentViewController(nextVC, animated: false, completion: nil)
}
}
答案 18 :(得分:1)
Swift 4.2
guard let someVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someVC") as? someVC else {
return
}
someVC.modalPresentationStyle = .overCurrentContext
present(someVC, animated: true, completion: nil)
答案 19 :(得分:1)
在iOS 7和iOS 8上测试的完整方法。
@interface UIViewController (MBOverCurrentContextModalPresenting)
/// @warning Some method of viewControllerToPresent will called twice before iOS 8, e.g. viewWillAppear:.
- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
@end
@implementation UIViewController (MBOverCurrentContextModalPresenting)
- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
UIViewController *presentingVC = self;
// iOS 8 before
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
UIViewController *root = presentingVC;
while (root.parentViewController) {
root = root.parentViewController;
}
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
[viewControllerToPresent dismissViewControllerAnimated:NO completion:^{
UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
if (orginalStyle != UIModalPresentationCurrentContext) {
root.modalPresentationStyle = UIModalPresentationCurrentContext;
}
[presentingVC presentViewController:viewControllerToPresent animated:NO completion:completion];
if (orginalStyle != UIModalPresentationCurrentContext) {
root.modalPresentationStyle = orginalStyle;
}
}];
}];
return;
}
UIModalPresentationStyle orginalStyle = viewControllerToPresent.modalPresentationStyle;
if (orginalStyle != UIModalPresentationOverCurrentContext) {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:completion];
if (orginalStyle != UIModalPresentationOverCurrentContext) {
viewControllerToPresent.modalPresentationStyle = orginalStyle;
}
}
@end
答案 20 :(得分:1)
如果您使用模态segue,请务必将其设置为此图像(如果需要,可以关闭动画)
答案 21 :(得分:0)
将导航的modalPresentationStyle
设置为UIModalPresentationCustom
并将您呈现的视图控制器的背景颜色设置为清晰的颜色。
答案 22 :(得分:0)
登录屏幕是一个模态,意味着它位于上一个屏幕的顶部。到目前为止,我们有模糊背景,但它并没有模糊任何东西;它只是一个灰色的背景。
首先,我们需要将View Controller的View背景更改为Clear color。它只是意味着它应该是透明的。默认情况下,该视图为白色。
其次,我们需要选择指向“登录”屏幕的“Segue”,并在“属性”检查器中将“演示文稿”设置为“当前上下文”。此选项仅适用于启用自动布局和大小类。
答案 23 :(得分:0)
:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[_window rootViewController]setModalPresentationStyle:UIModalPresentationCurrentContext];
return YES;
}
在您首先查看控制器,您必须从中加载下一个视图:
NextViewController *customvc = [[NextViewController alloc]init];
[self presentViewController:customvc animated:YES completion:^{
}];
在你的nextViewController中,它将被添加为透明:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
UIView* backView = [[UIView alloc] initWithFrame:self.view.frame];
backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
[self.view insertSubview:backView atIndex:0];
}