Fügen Sie vor allem eine UIView hinzu, auch die Navigationsleiste


180

Ich möchte vor allen anderen Ansichten, sogar der Navigationsleiste, eine Art "Popup" -Ansicht anzeigen, die so aussieht:

  • schwarzer Vollbildhintergrund mit einem Alpha von 0,5, um den anderen UIViewControllerdarunter zu sehen.
  • ein UIViewFenster in der Mitte mit einigen Informationen (ein Kalender, wenn Sie alles wissen wollen).

Zu diesem Zweck habe ich einen UIViewController erstellt, der die beiden UIViews(Hintergrund und Fenster) enthält, und ich versuche, ihn anzuzeigen. Ich habe es einfach versucht [mySuperVC addSubview:myPopUpVC.view], aber ich habe immer noch die Navigationsleiste oben.

Ich habe versucht, es als Modal darzustellen, aber die UIViewControllerUnterseite verschwindet und ich verliere meinen Transparenzeffekt.

Jede Idee dazu, ich bin sicher, es ist ganz einfach ...

Vielen Dank!


Fügen Sie Ihrem Anwendungsfenster eine Unteransicht hinzu. Der Umgang mit Orientierungsänderungen kann schwierig sein: stackoverflow.com/questions/8774495/…
Amar

Antworten:


196

Sie können dies tun, indem Sie Ihre Ansicht direkt zum keyWindow hinzufügen:

UIView *myView = /* <- Your custom view */;
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:myView];

UPDATE - Für Swift 4.1 und höher

let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(myView)

2
Danke :) Wenn Sie sich im Querformat befinden, müssen Sie die Ansicht leider drehen. Ich bin mir nicht sicher, wie ich das richtig machen soll.
Nicolas Roy

Ja, ich bin nur im Querformat und myView wird mit einer 90-Grad-Drehung angezeigt. Scheint das zu sein, worüber sie hier sprechen: stackoverflow.com/questions/8774495/…
Nicolas Roy

Das Orientierungsproblem tritt auf Geräten vor iOS8 auf, für die diese Lösung leider nicht funktioniert.
thgc

@NicolasRoy Autolayout wird helfen
Darmen Amanbayev

4
Die Registerkartenleiste wird nicht abgedeckt. Irgendeine Lösung dafür?
Manisha

134

[self.navigationController.view addSubview:overlayView]; ist was du wirklich willst


5
Sie müssen den Rahmen einstellen
Gabriel Goncalves

1
Sehr gute Lösung, insbesondere wenn Sie eine Ansicht als "Child View Controller" hinzufügen
Richard Topchii

2
Dies funktioniert nicht mit der Ansicht eines untergeordneten Ansichtscontrollers. Das Ändern der Z-Ebene der Navigationsleiste (wie Nam vorschlägt) funktioniert auch mit untergeordneten Ansichtssteuerungen.
Tapani

Es scheint eine elegantere Lösung zu sein, als dem Schlüsselfenster eine Ansicht hinzuzufügen. Wenn dies eine zusätzliche Ansicht gewährleistet, wird entlang der Animation der Basisansicht verschoben. Denn wenn die Ansicht im Schlüsselfenster hinzugefügt wird, enthält sie keine Animation und muss separat entfernt werden, wenn Sie den Controller schließen möchten.
Soan Saini

Es ist nicht über Popup, aber es ist genau das Richtige für meinen Fall. Danke))
Dilshod Zopirov

112

Hier ist eine einfache, elegante Lösung, die für mich funktioniert. Sie können die z-Position der Navigationsleiste unterhalb der Ansicht einstellen:

self.navigationController.navigationBar.layer.zPosition = -1;

Denken Sie daran, es auf 0 zurückzusetzen, wenn Sie fertig sind.


1
Dies funktioniert viel besser als das Hinzufügen der Überlagerungsansicht als Unteransicht zur Ansicht des Navigationscontrollers (was übrigens einen Absturz verursacht). Diese Z-Position-Lösung ist wahrscheinlich viel zuverlässiger und verursacht in Zukunft weniger Probleme.
Tapani

Dies funktioniert hervorragend bei der Arbeit mit Storyboards. Sie können die Ansicht im Storyboard hinzufügen!
Jos Koomen

Funktioniert auch gut für mich. Es wäre großartig zu erwähnen, dass zPosition auf den Wert 0 zurückgesetzt werden sollte (Sie erwähnen nur, dass es zurückgesetzt werden sollte, wenn Sie fertig sind). Und ich habe tabBar (von TabBarController auch auf meinem Bildschirm. Ich habe versucht, zPosition festzulegen, aber als ich auf 0 zurückkam, war tabBar noch nicht sichtbar. Für tabBar ist es besser, die isHidden-Eigenschaft zu verwenden.
Libor Zapletal

1
Arbeiten Sie nicht mit Barrierefreiheit. Wenn Sie über die Ansicht schwenken, wird sie nicht fokussiert.
Antonjn

Ich liebe dich!! <3
chr0x

57

Schnelle Versionen für die überprüfte Antwort:

Swift 4:

let view = UIView()
view.frame = UIApplication.shared.keyWindow!.frame
UIApplication.shared.keyWindow!.addSubview(view)

Swift 3.1:

let view = UIView()
view.frame = UIApplication.sharedApplication().keyWindow!.frame 
UIApplication.sharedApplication().keyWindow!.addSubview(view)

6
Kann ich dafür sorgen, dass alle aktuellen Ansichten (View Controller) abgedeckt werden, aber der neu erscheinende View Controller darüber angezeigt wird?
Michał Ziobro

24

Fügen Sie Ihre Ansicht als Unteransicht von NavigationController hinzu.

[self.navigationController.navigationBar addSubview: overlayView)]

Sie können es auch über das Fenster hinzufügen:

UIView *view = /* Your custom view */;
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:view];

Hoffe das hilft.. :)


Die Übersicht kommt, aber wenn das Hinzufügen einer Schaltfläche keine Schaltflächenaktion ausführen oder keinen benutzerdefinierten Beschriftungstext für die Übersicht festlegen kann
Vineesh TP

Funktioniert gut für mich:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Arthur Clemens


11

Die Antwort von @ Nam funktioniert hervorragend, wenn Sie nur Ihre benutzerdefinierte Ansicht anzeigen möchten, Ihre benutzerdefinierte Ansicht jedoch eine Benutzerinteraktion erfordert. Sie müssen die Interaktion für die deaktivierennavigationBar .

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

Wie in Nams Antwort gesagt, vergessen Sie nicht, diese Änderungen rückgängig zu machen:

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


Mit einer Erweiterung können Sie dies besser tun:

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

Und benutze es einfach so:

self.navigationController.navigationBar.toggle()

1
perfekte Lösung.. !! Versuchte so viele Dinge und verbrachte so viel Zeit .. aber das funktioniert gut .. !!
Dishant

8

Schnelle Version der Antwort von @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
}

Vergessen Sie nicht, dass das Fenster eine starke Eigenschaft sein muss, da die ursprüngliche Antwort zu einer sofortigen Freigabe des Fensters führt


6

Ich empfehle Ihnen, ein neues UIWindow zu erstellen:

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];

Anschließend können Sie Ihre Ansicht in einem anderen UIViewController verwalten. So entfernen Sie die Fenster:

[window removeFromSuperview];
window = nil;

hoffe das wird helfen!


3
Danke, aber ich denke, etwas fehlt, weil nichts erscheint: /
Nicolas Roy

6

Es gibt mehr als einen Weg, dies zu tun:

1- Fügen Sie Ihr UIViewOn hinzu, UIWindowanstatt es hinzuzufügen UIViewController. Auf diese Weise wird es alles im Griff haben.

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

2- Verwenden Sie einen benutzerdefinierten Übergang, bei dem Ihr UIViewController mit einem Alpha von 0,5 im Hintergrund angezeigt wird

Dafür empfehle ich Ihnen Folgendes: https://github.com/Citrrus/BlurryModalSegue


4
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];

2

Hinweis: Wenn Sie eine Ansicht im Vollbildmodus hinzufügen möchten, verwenden Sie nur den folgenden Code

Fügen Sie diese Erweiterung von UIViewController hinzu

public extension UIViewController {
   internal func makeViewAsFullScreen() {
      var viewFrame:CGRect = self.view.frame
      if viewFrame.origin.y > 0 || viewFrame.origin.x > 0 {
        self.view.frame = UIScreen.main.bounds
      }
   }
}

Fahren Sie wie gewohnt mit dem Hinzufügen der Unteransicht fort

Verwenden Sie jetzt beim Hinzufügen von viewDidAppear von UIViewController

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

     self.makeViewAsFullScreen()
}

2

In Swift 4.2 und Xcode 10

var spinnerView: UIView? //This is your view

spinnerView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
//Based on your requirement change width and height like self.view.bounds.size.width
spinnerView?.backgroundColor = UIColor.black.withAlphaComponent(0.6)
//        self.view.addSubview(spinnerView)
let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(spinnerView!)

In Ziel C.

UIView * spinnerView; // Dies ist Ihre Ansicht

self.spinnerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height)];  
//Based on your requirement change width and height like self.view.bounds.size.width
self.spinnerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
// [self.view addSubview:self.spinnerView];
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:self.spinnerView];

Dies kann nur im Hoch- oder Querformatmodus funktionieren.

Ein weiterer einfacher Code ist:

yourViewName.layer.zPosition = 1//Change you view name

1

Ich würde eine UIViewController-Unterklasse verwenden, die eine "Container-Ansicht" enthält, in die Ihre anderen Ansichts-Controller eingebettet sind. Anschließend können Sie den Navigationscontroller in der Containeransicht hinzufügen (z. B. mithilfe des Segues für die Einbettungsbeziehung).

Siehe Implementieren eines Container View Controllers


1
UIApplication.shared.keyWindow?.insertSubview(yourView, at: 1)

Diese Methode funktioniert mit xcode 9.4, iOS 11.4


0
[self.navigationController.navigationBar.layer setZPosition:-0.1];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 20, 35, 35)];
[view setBackgroundColor:[UIColor redColor]];
[self.navigationController.view addSubview:view];
[self.navigationController.view bringSubviewToFront:view];
self.navigationController.view.clipsToBounds = NO;
[self.navigationController.navigationBar.layer setZPosition:0.0];

Geben Sie hier die Bildbeschreibung ein


0

Sie müssen dem ersten Fenster eine Unteransicht mit dem Typ UITextEffectsWindow hinzufügen. Zum einen, weil benutzerdefinierte Tastaturen ihr UITextEffectsWindow hinzufügen und wenn Sie eine Unteransicht hinzufügen, funktioniert dies nicht richtig. Sie können dem letzten Fenster auch keine Unteransicht hinzufügen, da die Tastatur beispielsweise auch ein Fenster ist und Sie nicht über das Tastaturfenster präsentieren können. Die beste Lösung, die ich gefunden habe, besteht darin, dem ersten Fenster mit dem Typ UITextEffectsWindow eine Unteransicht (oder sogar einen Push-View-Controller) hinzuzufügen. Dieses Fenster behandelt die Zubehöransicht, die Navigationsleiste - alles.

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.