Aggiungi una vista UIV soprattutto, anche la barra di navigazione


181

Voglio visualizzare, sopra ogni altra vista, anche la barra di navigazione, una sorta di vista "pop-up" che assomiglia a questa:

  • schermo nero a sfondo nero con 0,5 alfa per vedere l'altro UIViewControllersotto.
  • una UIViewfinestra nel mezzo con alcune informazioni (un calendario se vuoi sapere tutto).

Per fare ciò, ho creato un UIViewController che contiene i due UIViews(sfondo e finestra) e sto provando a visualizzarlo. Ho provato un semplice [mySuperVC addSubview:myPopUpVC.view], ma ho ancora la barra di navigazione sopra.

Ho provato a presentarlo come modale, ma la parte UIViewControllerinferiore scompare e perdo il mio effetto di trasparenza.

Qualche idea per farlo, sono sicuro che sia abbastanza semplice ...

Grazie!


Aggiungi una visualizzazione secondaria nella finestra dell'applicazione. Gestire i cambiamenti di orientamento può essere complicato: stackoverflow.com/questions/8774495/…
Amar

Risposte:


197

Puoi farlo aggiungendo la tua vista direttamente alla finestra chiave:

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

AGGIORNAMENTO - Per Swift 4.1 e versioni successive

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

2
Grazie :) Sfortunatamente se sei in modalità orizzontale devi ruotare la vista. Non sono sicuro di saperlo fare correttamente.
Nicolas Roy,

Sì, sono solo in modalità orizzontale e myView appare con una rotazione di 90 gradi. Sembra essere quello di cui stanno parlando qui: stackoverflow.com/questions/8774495/…
Nicolas Roy,

Il problema dell'orientamento si verifica su dispositivi pre-iOS8, per i quali questa soluzione purtroppo non funziona.
dal

@NicolasRoy Autolayout aiuterà
Darmen Amanbayev,

4
non copre la barra delle schede. Qualche soluzione per quello?
Manisha,

134

[self.navigationController.view addSubview:overlayView]; è quello che vuoi davvero


5
Devi impostare il frame
Gabriel Goncalves il

1
Ottima soluzione, soprattutto, quando aggiungi una vista come "controller vista figlio"
Richard Topchii,

2
Questo non funziona con la vista di un controller vista figlio. La modifica del livello z della barra di navigazione (come suggerisce Nam) funziona anche con i controller di visualizzazione figlio.
Tapani,

Sembra una soluzione più elegante dell'aggiunta della vista alla finestra Chiave. Poiché ciò garantisce una vista aggiunta, si sposta lungo l'animazione della vista di base. Perché se la vista viene aggiunta nella finestra della chiave non viene fornita con l'animazione e deve essere rimossa separatamente se si desidera chiudere il controller.
soan saini,

non si tratta di popup ma è la cosa giusta per il mio caso. Grazie))
Dilshod Zopirov l'

112

Ecco una soluzione semplice ed elegante che funziona per me. È possibile impostare la posizione z della barra di navigazione su sotto la vista:

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

Al termine, ricorda di riportarlo a 0.


1
Funziona molto meglio dell'aggiunta della vista overlay come sottoview alla vista del controller di navigazione (che comunque provoca un arresto anomalo). Questa soluzione con posizione z probabilmente è molto più affidabile e causa meno problemi in futuro.
Tapani,

Funziona benissimo quando si lavora con storyboard. Puoi aggiungere la vista all'interno dello storyboard!
Jos Koomen,

Funziona benissimo anche per me. Sarebbe bello ricordare che zPosition dovrebbe essere riportato al valore 0 (hai appena detto che dovrebbe essere ripristinato una volta terminato). E ho tabBar (anche da TabBarController nella mia schermata. Ho provato a impostare zPosition ma quando tornando al valore 0 tabBar non era ancora visibile. Quindi per tabBar è meglio usare la proprietà isHidden.
Libor Zapletal

1
Non lavorare con l'accessibilità. La panoramica sulla vista non la focalizzerà.
antonjn,

Ti amo!! <3
chr0x

57

Versioni rapide per la risposta selezionata:

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
Posso rendere questa copertina tutta la vista corrente (controller di visualizzazione), ma lasciare un nuovo controller di visualizzazione visualizzato sopra di esso?
Michał Ziobro,

24

Aggiungi la vista come sottoview di NavigationController.

[self.navigationController.navigationBar addSubview: overlayView)]

Puoi anche aggiungerlo dalla finestra:

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

Spero che questo ti aiuti.. :)


La vista è in arrivo ma, quando aggiungi un pulsante non è possibile ottenere l'azione del pulsante o impostare il testo dell'etichetta personalizzata su overView
Vineesh TP

Funziona bene per me:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Arthur Clemens,

22

Ottima soluzione Dalef in rapido:

self.navigationController?.view.addSubview(view)

11

La risposta di @ Nam funziona benissimo se vuoi solo visualizzare la tua vista personalizzata ma se la tua vista personalizzata necessita dell'interazione dell'utente, devi disabilitare l'interazione per ilnavigationBar .

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

Come detto nella risposta di Nam, non dimenticare di invertire questi cambiamenti:

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


Puoi farlo in un modo migliore con un'estensione:

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

E semplicemente usalo in questo modo:

self.navigationController.navigationBar.toggle()

1
soluzione perfetta .. !! Ho provato così tante cose e ho trascorso così tanto tempo .. ma questo funziona benissimo .. !!
Dishant

8

Versione rapida della risposta di @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
}

Non dimenticare che la finestra deve essere una proprietà forte, poiché la risposta originale porta a una deallocazione immediata della finestra


6

Ti consiglio di creare una nuova 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];

Quindi puoi gestire la tua vista in un altro UIViewController. Per rimuovere le finestre:

[window removeFromSuperview];
window = nil;

spero che possa aiutare!


3
Grazie, ma penso che manchi qualcosa perché non appare nulla: /
Nicolas Roy,

6

C'è più di un modo per farlo:

1- Aggiungi il tuo UIViewon UIWindowinvece di aggiungerlo su UIViewController. In questo modo sarà al di sopra di tutto.

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

2- Utilizza la transizione personalizzata che manterrà il tuo UIViewController visualizzato nella parte posteriore con 0,5 alfa

Per questo ti consiglio di guardare questo: https://github.com/Citrrus/BlurryModalSegue


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

3

In Swift 4.2 e 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 Objective C

UIView * spinnerView; // Questa è la tua vista

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

Questo può funzionare solo in modalità verticale o orizzontale.

Un altro codice semplice è:

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

2

Nota se si desidera aggiungere la visualizzazione a schermo intero, utilizzare solo il codice seguente

Aggiungi queste estensioni di UIViewController

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
      }
   }
}

Continua come normale processo di aggiunta di sottoview

Ora usa l'aggiunta di UIViewController viewDidAppear

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

     self.makeViewAsFullScreen()
}

1

Userei una sottoclasse UIViewController contenente una "Vista contenitore" che incorpora i tuoi altri controller di vista. Sarai quindi in grado di aggiungere il controller di navigazione all'interno della Vista contenitore (ad esempio, utilizzando la relazione di incorporamento segue).

Vedere Implementazione di un controller vista contenitore


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

Questo metodo funziona con 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];

inserisci qui la descrizione dell'immagine


0

Devi aggiungere una sottoview alla prima finestra con il tipo UITextEffectsWindow. Al primo, perché le tastiere personalizzate aggiungono la loro UITextEffectsWindow e se aggiungi una sottoview ad essa non funzionerà correttamente. Inoltre, non è possibile aggiungere una visualizzazione secondaria all'ultima finestra perché la tastiera, ad esempio, è anche una finestra e non è possibile presentarla dalla finestra della tastiera. Quindi la migliore soluzione che ho trovato è quella di aggiungere subview (o persino spingere il controller di visualizzazione) alla prima finestra con il tipo UITextEffectsWindow, questa finestra copre la vista degli accessori, la barra di navigazione - tutto.

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.