我想在任何其他视图,甚至是导航栏上,显示一种“弹出”视图,看起来像这样:

全屏黑色背景,0.5 alpha,可以看到下面的另一个UIViewController。 中间有一个带有一些信息的UIView窗口,(如果你想知道一切,一个日历)。

为了做到这一点,我已经创建了一个UIViewController,它包含了两个uiview (background和window),我试图显示它。我尝试了一个简单的[mySuperVC addSubview:myPopUpVC。视图],但我仍然有上面的导航栏。

我试着把它表示为一个模态,但是下面的UIViewController消失了,我失去了透明效果。

有什么办法可以做到这一点吗,我相信这很简单……

谢谢!


当前回答

@Nicolas Bonnet回答的快速版本:

    var popupWindow: UIWindow?

func showViewController(controller: UIViewController) {
    self.popupWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
    controller.view.frame = self.popupWindow!.bounds
    self.popupWindow!.rootViewController = controller
    self.popupWindow!.makeKeyAndVisible()
}

func viewControllerDidRemove() {
    self.popupWindow?.removeFromSuperview()
    self.popupWindow = nil
}

不要忘记,窗口必须是一个强属性,因为最初的答案会导致立即释放窗口

其他回答

我建议你创建一个新的UIWindow:

UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.rootViewController = viewController;
window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
window.opaque = NO;
window.windowLevel = UIWindowLevelCFShareCircle;
window.backgroundColor = [UIColor clearColor];

[window makeKeyAndVisible];

然后你可以在另一个UIViewController中管理你的视图。 拆除窗户:

[window removeFromSuperview];
window = nil;

希望对大家有所帮助!

做这件事的方法不止一种:

1-在UIWindow上添加你的UIView而不是在UIViewController上添加。这样的话,它就会在一切之上。

   [[(AppDelegate *)[UIApplication sharedApplication].delegate window] addSubview:view];

2-使用自定义过渡,将保持你的UIViewController显示在后面的0.5 alpha

为此,我建议你看看这个:https://github.com/Citrrus/BlurryModalSegue

@Nicolas Bonnet回答的快速版本:

    var popupWindow: UIWindow?

func showViewController(controller: UIViewController) {
    self.popupWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
    controller.view.frame = self.popupWindow!.bounds
    self.popupWindow!.rootViewController = controller
    self.popupWindow!.makeKeyAndVisible()
}

func viewControllerDidRemove() {
    self.popupWindow?.removeFromSuperview()
    self.popupWindow = nil
}

不要忘记,窗口必须是一个强属性,因为最初的答案会导致立即释放窗口

@Nam的答案是伟大的,如果你只是想显示你的自定义视图,但如果你的自定义视图需要用户交互,你需要禁用导航栏的交互。

self.navigationController.navigationBar.layer.zPosition = -1
self.navigationController.navigationBar.isUserInteractionEnabled = false

就像Nam的回答中所说的,不要忘记逆转这些变化:

self.navigationController.navigationBar.layer.zPosition = 0
self.navigationController.navigationBar.isUserInteractionEnabled = true

你可以用一个扩展更好的方式做到这一点:

extension UINavigationBar {
    func toggle() {
        if self.layer.zPosition == -1 {
            self.layer.zPosition = 0
            self.isUserInteractionEnabled = true
        } else {
            self.layer.zPosition = -1
            self.isUserInteractionEnabled = false
        }
    }
}

就像这样简单地使用它:

self.navigationController.navigationBar.toggle()

You need to add a subview to the first window with the UITextEffectsWindow type. To the first, because custom keyboards add their UITextEffectsWindow, and if you add a subview to it this won't work correctly. Also, you cannot add a subview to the last window because the keyboard, for example, is also a window and you can`t present from the keyboard window. So the best solution I found is to add subview (or even push view controller) to the first window with UITextEffectsWindow type, this window covers accessory view, navbar - everything.

let myView = MyView()
myView.frame = UIScreen.main.bounds

guard let textEffectsWindow = NSClassFromString("UITextEffectsWindow") else { return }
let window = UIApplication.shared.windows.first { window in
    window.isKind(of: textEffectsWindow)
}
window?.rootViewController?.view.addSubview(myView)