80

我正在显示一个模态视图

[self presentModalViewController:controller animated:YES];

当视图在屏幕上移动时,根据创建它的 xib 文件中的设置,它是透明的,但是一旦它填满屏幕,它就会变得不透明。

无论如何保持视图透明?

我怀疑它被放置的视图没有被渲染,而不是模态视图变得不透明。

4

21 回答 21

85

在 iOS 3.2 之后,有一种方法可以做到这一点而无需任何“技巧”——请参阅 modalPresentationStyle 属性的文档。您有一个 rootViewController,它将显示 viewController。所以这是成功的代码:

viewController.view.backgroundColor = [UIColor clearColor];
rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[rootViewController presentModalViewController:viewController animated:YES];

使用此方法,viewController 的背景将是透明的,并且底层的 rootViewController 将是可见的。请注意,这似乎只适用于 iPad,请参阅下面的评论。

于 2011-04-07T09:49:57.193 回答
63

您的视图仍然是透明的,但是一旦您的模态控制器位于堆栈的顶部,它后面的视图就会被隐藏(就像任何最顶层的视图控制器一样)。解决方案是自己手动为视图设置动画;那么后面的viewController就不会被隐藏(因为你不会'离开'它)。

于 2009-02-25T21:22:55.407 回答
48

我需要让它工作:

self.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
于 2013-01-19T16:19:34.087 回答
24

对于那些想要查看一些代码的人,这是我添加到透明视图控制器中的内容:

// Add this view to superview, and slide it in from the bottom
- (void)presentWithSuperview:(UIView *)superview {
    // Set initial location at bottom of superview
    CGRect frame = self.view.frame;
    frame.origin = CGPointMake(0.0, superview.bounds.size.height);
    self.view.frame = frame;
    [superview addSubview:self.view];            

    // Animate to new location
    [UIView beginAnimations:@"presentWithSuperview" context:nil];
    frame.origin = CGPointZero;
    self.view.frame = frame;
    [UIView commitAnimations];
}

// Method called when removeFromSuperviewWithAnimation's animation completes
- (void)animationDidStop:(NSString *)animationID
                finished:(NSNumber *)finished
                 context:(void *)context {
    if ([animationID isEqualToString:@"removeFromSuperviewWithAnimation"]) {
        [self.view removeFromSuperview];
    }
}

// Slide this view to bottom of superview, then remove from superview
- (void)removeFromSuperviewWithAnimation {
    [UIView beginAnimations:@"removeFromSuperviewWithAnimation" context:nil];

    // Set delegate and selector to remove from superview when animation completes
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    // Move this view to bottom of superview
    CGRect frame = self.view.frame;
    frame.origin = CGPointMake(0.0, self.view.superview.bounds.size.height);
    self.view.frame = frame;

    [UIView commitAnimations];    
}
于 2009-08-30T15:55:14.807 回答
19

在 iOS 8 中,Apple 批准的方法是将 modalPresentationStyle 设置为 'UIModalPresentationOverCurrentContext'。

从 UIViewController 文档:

UIModalPresentationOverCurrentContext

仅在父视图控制器的内容上显示内容的演示样式。演示结束时,所呈现内容下方的视图不会从视图层次结构中删除。因此,如果呈现的视图控制器没有用不透明的内容填充屏幕,则底层内容会显示出来。

在弹出窗口中呈现视图控制器时,仅当过渡样式为 UIModalTransitionStyleCoverVertical 时才支持此呈现样式。尝试使用不同的转换样式会触发异常。但是,如果父视图控制器不在弹出窗口中,您可以使用其他转换样式(部分卷曲转换除外)。

在 iOS 8.0 及更高版本中可用。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/

WWDC 2014 中的“iOS 8 中的视图控制器改进”视频对此进行了详细介绍。

确保为您呈现的视图控制器提供清晰的背景颜色(否则,它仍然会显得不透明)。

于 2014-09-23T08:12:56.533 回答
16

还有另一种选择:在显示模态控制器之前,捕获整个窗口的屏幕截图。将捕获的图像插入 UIImageView 并将图像视图添加到您将要显示的控制器视图中。然后送回去。在图像视图上方插入另一个视图(背景黑色,alpha 0.7)。显示您的模态控制器,它看起来像是透明的。刚刚在运行 iOS 4.3.1 的 iPhone 4 上尝试过。喜欢魅力。

于 2011-03-26T00:04:42.223 回答
10

这已经很老了,但我解决了以下相同的问题:由于我需要在 iPhone 中显示导航控制器,因此添加子视图不是一个可行的解决方案。

所以我做了什么:

1) 在展示视图控制器之前,对当前屏幕进行截图:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

2)创建您要呈现的视图控制器,并将背景添加为子视图,将其发送到后面。

UIViewController * presentingVC = [UIViewController new];
UIImageView * backgroundImageOfPreviousScreen = [[UIImageView alloc] initWithImage:backgroundImage];
[presentingVC.view addSubview:backgroundImageOfPreviousScreen];
[presentingVC.view sendSubviewToBack:backgroundImageOfPreviousScreen];

3) 展示您的视图控制器,但在此之前在新视图控制器中,在 viewDidLoad 中添加一个透明视图(我使用了 ILTranslucentView)

-(void)viewDidLoad
{
    [super viewDidLoad];
    ILTranslucentView * translucentView = [[ILTranslucentView alloc] initWithFrame:self.view.frame];
    [self.view addSubview:translucentView];
    [self.view sendSubviewToBack:translucentView];
}

就这样!

于 2014-03-08T16:23:51.167 回答
5

我在另一个问题中写下了我的发现,但要点是你必须调用modalPresentationStyle = UIModalPresentationCurrentContext目前拥有全屏的任何东西。大多数时候,它是 [UIApplication sharedApplication].delegate.window 的 rootViewController。它也可能是一个新的 UIViewController,它带有modalPresentationStyle = UIModalPresentationFullScreen.

如果您想知道我是如何专门解决这个问题的,请阅读我的其他更详细的帖子。祝你好运!

于 2012-10-26T10:14:14.523 回答
5

这似乎在 IOS 8 中被破坏了,我正在使用导航控制器,并且正在显示的上下文是导航菜单上下文,在我们的例子中是滑动菜单控制器。

我们正在使用 pod 'TWTsideMenuViewController', '0.3' 尚未检查这是否是库或上述方法的问题。

于 2014-09-15T17:44:14.810 回答
5

这在 iOS 8-9 中对我有用:

1- 使用 alpha 设置视图控制器的背景

2-添加此代码:

TranslucentViewController *tvc = [[TranslucentViewController alloc] init];
self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[tvc setModalPresentationStyle:UIModalPresentationOverCurrentContext];

[self.navigationController presentViewController:tvc animated:YES completion:nil];
于 2015-10-24T06:42:11.973 回答
4

我知道这是一个很老的问题。我被困在这个问题上,我能够从这个线程中获得线索。所以把我的工作原理放在这里:)。我正在使用情节提要,并且已经转到要呈现的 ViewController。视图控制器具有透明的背景颜色。现在在 segue 的属性检查器中,我将演示文稿设置为“在当前上下文中”。它对我有用。我正在为 iPhone 开发。

segue的属性检查器

于 2016-05-06T15:10:59.353 回答
3

在我的情况下,我在同一个 viewController 上有视图。所以制作一个新的视图控制器来保存 UIView。通过设置它的 alpha 属性使该视图透明。然后在一个按钮上单击我写了这段代码。这看起来不错的样子。

UIGraphicsBeginImageContext(objAppDelegate.window.frame.size);
    [objAppDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();



    UIViewController *controllerForBlackTransparentView=[[[UIViewController alloc] init] autorelease];
    [controllerForBlackTransparentView setView:viewForProfanity];

    UIImageView *imageForBackgroundView=[[UIImageView alloc] initWithFrame:CGRectMake(0, -20, 320, 480)];
    [imageForBackgroundView setImage:viewImage];

    [viewForProfanity insertSubview:imageForBackgroundView atIndex:0];

    [self.navigationController presentModalViewController:controllerForBlackTransparentView animated:YES];

它显示了我想要的。希望对某人有所帮助。

于 2011-07-15T07:27:08.060 回答
3

我创建了开放源库MZFormSheetController以在其他 UIWindow 上呈现模态表单。您可以使用它来呈现透明度模态视图控制器,甚至可以调整呈现的视图控制器的大小。

于 2013-08-10T17:57:29.250 回答
2

这是我创建的一个可以解决问题的类别。

    //
    //  UIViewController+Alerts.h
    //

    #import <UIKit/UIKit.h>

    @interface UIViewController (Alerts)

    - (void)presentAlertViewController:(UIViewController *)alertViewController animated:(BOOL)animated;
    - (void)dismissAlertViewControllerAnimated:(BOOL)animated;

    @end


    //
    //  UIViewController+Alerts.m
    //

    #import "UIViewController+Alerts.h"

    @implementation UIViewController (Alerts)

    - (void)presentAlertViewController:(UIViewController *)alertViewController animated:(BOOL)animated
    {
            // Setup frame of alert view we're about to display to just off the bottom of the view
            [alertViewController.view setFrame:CGRectMake(0, self.view.frame.size.height, alertViewController.view.frame.size.width, alertViewController.view.frame.size.height)];

            // Tag this view so we can find it again later to dismiss
            alertViewController.view.tag = 253;

            // Add new view to our view stack
            [self.view addSubview:alertViewController.view];

            // animate into position
            [UIView animateWithDuration:(animated ? 0.5 : 0.0) animations:^{
                    [alertViewController.view setFrame:CGRectMake(0, (self.view.frame.size.height - alertViewController.view.frame.size.height) / 2, alertViewController.view.frame.size.width, alertViewController.view.frame.size.height)];
            }];      
    }

    - (void)dismissAlertViewControllerAnimated:(BOOL)animated
    {
            UIView *alertView = nil;

            // find our tagged view
            for (UIView *tempView in self.view.subviews)
            {
                    if (tempView.tag == 253)
                    {
                            alertView = tempView;
                            break;
                    }
            }

            if (alertView)
            {
                    // clear tag
                    alertView.tag = 0;

                    // animate out of position
                    [UIView animateWithDuration:(animated ? 0.5 : 0.0) animations:^{
                            [alertView setFrame:CGRectMake(0, self.view.frame.size.height, alertView.frame.size.width, alertView.frame.size.height)];
                    }];      
            }
    }

    @end
于 2012-01-17T12:15:51.130 回答
2

经过大量研究后,看起来这将解决我们的问题并达到我们的目的。

使用标识符创建从源 VC 到目标 VC 的 segue。

例如“goToDestinationViewController”可以让生活变得轻松让我们考虑当前的视图控制器,即你想要在透明视图后面的那个作为源,目的地作为目的地

现在在 viewDidLoad: 或视图中的源 VC

performSegueWithIdentifier("goToDestinationViewController", sender: nil)

很好,我们已经完成了一半。现在去你的故事板。点击转场。应该是这样的: segue

将选项更改为显示的内容。

现在是真正的解决方案。

在您的目标视图控制器的 viewDidLoad 中添加此代码。

self.modalPresentationStyle = .Custom

..................................................... ........................这很容易............ .........................................................

于 2016-06-17T01:58:23.100 回答
1

另一种方法是使用“容器视图”。只需将 alpha 设为 1 以下并嵌入 sequ。XCode 5,针对 iOS7。

无法显示图像,没有足够的声誉)))

iOS6 提供的容器视图。

于 2013-08-14T09:29:17.040 回答
1

此代码在 iOS6 和 iOS7 下的 iPhone 上运行良好:

presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];

但是沿着这种方式,您会失去“从底部滑动”的动画。

于 2013-09-22T23:20:57.383 回答
1

我为 iOS 7 及更高版本找到了这个优雅而简单的解决方案!

对于 iOS 8,Apple 添加了 UIModalPresentationOverCurrentContext,但它不适用于 iOS 7 及之前的版本,因此我无法将其用于我的案例。

请创建类别并输入以下代码。

.h 文件

typedef void(^DismissBlock)(void);

@interface UIViewController (Ext)

- (DismissBlock)presentController:(UIViewController *)controller
              withBackgroundColor:(UIColor *)color
                         andAlpha:(CGFloat)alpha
                presentCompletion:(void(^)(void))presentCompletion;

@end

.m 文件

#import "UIViewController+Ext.h"

@implementation UIViewController (Ext)

- (DismissBlock)presentController:(UIViewController *)controller
              withBackgroundColor:(UIColor *)color
                         andAlpha:(CGFloat)alpha
                presentCompletion:(void(^)(void))presentCompletion
{
    controller.modalPresentationStyle = UIModalPresentationCustom;

    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    __block UIView *overlay = [[UIView alloc] initWithFrame:keyWindow.bounds];
    if (color == nil) {
        color = [UIColor blackColor];
    }
    overlay.backgroundColor = color;
    overlay.alpha = alpha;

    if (self.navigationController != nil) {
        [self.navigationController.view addSubview:overlay];
    }
    else if (self.tabBarController != nil) {
        [self.tabBarController.view addSubview:overlay];
    }
    else {
        [self.view addSubview:overlay];
    }

    self.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:controller
                       animated:true
                     completion:presentCompletion];

    DismissBlock dismissBlock = ^(void) {
        [self dismissViewControllerAnimated:YES completion:nil];
        [UIView animateWithDuration:0.25
                         animations:^{
                             overlay.alpha = 0;
                         } completion:^(BOOL finished) {
                             [overlay removeFromSuperview];
                         }];
    };
    return dismissBlock;
}

@end

注意:它也适用于 navigationContoller、tabBarController。

使用示例:

       // Please, insure that your controller has clear background
       ViewController *controller = [ViewController instance];
        __block DismissBlock dismissBlock = [self presentController:controller
                                                withBackgroundColor:[UIColor blackColor]
                                                           andAlpha:0.5
                                                  presentCompletion:nil];
        // Supposed to be your controller's closing callback
        controller.dismissed = ^(void) {
            dismissBlock();
        };

好好享受!请留下一些反馈。

于 2016-06-09T14:28:34.750 回答
0

这是迄今为止我发现的最好和最干净的方法:

@protocol EditLoginDelegate <NSObject>

- (void)dissmissEditLogin;

@end

- (IBAction)showtTransparentView:(id)sender {

    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"foo bar"
                                                         delegate:self
                                                cancelButtonTitle:@"cancel"
                                           destructiveButtonTitle:@"destructive"
                                                otherButtonTitles:@"ok", nil];

    [actionSheet showInView:self.view];

}

- (void)willPresentActionSheet:(UIActionSheet *)actionSheet{

    UIStoryboard *loginStoryboard     = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
    self.editLoginViewController      = [loginStoryboard instantiateViewControllerWithIdentifier:@"EditLoginViewController"];

    self.editLoginViewController.delegate = self;

    [self.editLoginViewController viewWillAppear:NO];
    [actionSheet addSubview:self.editLoginViewController.view];
    [self.editLoginViewController viewDidAppear:NO];
}
于 2013-09-11T17:24:06.120 回答
0

我遇到的最佳解决方案是使用 addChildViewController 方法。这是一个很好的例子:将子视图控制器的视图添加到父视图控制器的子视图中

于 2014-08-01T13:31:03.427 回答
0

我尝试使用多种方法解决但仍然失败,最终实现以下代码。

斯威夫特的决议:

// A.swift init method
modalPresentationStyle = .currentContext // or overCurrentContent
modalTransitionStyle = .crossDissolve // dissolve means overlay

然后在 B 视图控制器中:</p>

// B.swift
let a = A()
self.present(a, animated: true, completion: nil)
于 2018-09-02T06:54:25.640 回答