Dodaj przede wszystkim UIView, nawet pasek nawigacyjny

181

Chcę wyświetlić, ponad wszystkimi innymi widokami, nawet pasek nawigacji, rodzaj „wyskakującego” widoku, który wygląda następująco:

  • na pełnym ekranie czarne tło z 0,5 alfa, aby zobaczyć drugie UIViewControllerpod spodem.
  • UIViewokno w środku z niektórych informacji (kalendarz, jeśli chcesz wiedzieć wszystko).

Aby to zrobić, utworzyłem UIViewController, który zawiera dwa elementy UIViews(tło i okno) i próbuję je wyświetlić. Wypróbowałem prosty [mySuperVC addSubview:myPopUpVC.view], ale nadal mam pasek nawigacji powyżej.

Próbowałem przedstawić go jako modal, ale UIViewControllerspód znika i tracę efekt przezroczystości.

Każdy pomysł, aby to zrobić, jestem pewien, że to dość proste ...

Dzięki!

Nicolas Roy
źródło
Dodaj widok podrzędny w oknie aplikacji. Obsługa zmian orientacji może być trudna: stackoverflow.com/questions/8774495/…
Amar

Odpowiedzi:

197

Możesz to zrobić, dodając widok bezpośrednio do keyWindow:

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

AKTUALIZACJA - dla Swift 4.1 i nowszych

let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(myView)
Rom.
źródło
2
Dzięki :) Niestety, jeśli jesteś w trybie poziomym, musisz obrócić widok. Nie jestem pewien, czy wiem jak to zrobić poprawnie.
Nicolas Roy
Tak, jestem tylko w trybie poziomym, a myView pojawia się z obrotem o 90 stopni. Wygląda na to, o czym tu mówią: stackoverflow.com/questions/8774495/...
Nicolas Roy
Problem z orientacją występuje na urządzeniach starszych niż iOS8, dla których to rozwiązanie niestety nie działa.
thgc
@NicolasRoy Autolayout pomoże
Darmen Amanbayev
4
nie obejmuje paska kart. Jakieś rozwiązanie tego?
Manisha
134

[self.navigationController.view addSubview:overlayView]; jest tym, czego naprawdę chcesz

dalef
źródło
5
Musisz ustawić ramkę
Gabriel Goncalves
1
Bardzo dobre rozwiązanie, zwłaszcza gdy dodajesz widok jako „kontroler widoku dziecka”
Richard Topchii
2
Nie działa to z widokiem kontrolera widoku potomnego. Zmiana poziomu Z paska nawigacyjnego (jak sugeruje Nam) działa również z kontrolerami widoku potomnego.
Tapani,
Wygląda na bardziej eleganckie rozwiązanie niż dodawanie widoku do okna klucza. Ponieważ zapewnia to dodatkowy widok, porusza się wzdłuż animacji widoku podstawowego. Ponieważ jeśli widok jest dodawany do okna klucza, nie jest dostarczany z animacją i musi zostać oddzielnie usunięty, jeśli chcesz zamknąć kontroler.
soan saini
nie jest to wyskakujące okienko, ale w moim przypadku jest to właściwe rozwiązanie Dzięki))
Dilshod Zopirov
112

Oto proste, eleganckie rozwiązanie, które działa dla mnie. Możesz ustawić pozycję Z paska nawigacji na poniżej widoku:

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

Pamiętaj, aby po zakończeniu ustawić go z powrotem na 0.

Nam
źródło
1
Działa to znacznie lepiej niż dodawanie widoku nakładki jako widoku podrzędnego do widoku kontrolera nawigacji (który, nawiasem mówiąc, powoduje awarię). To rozwiązanie dla pozycji Z jest prawdopodobnie bardziej niezawodne i powoduje mniej problemów w przyszłości.
Tapani,
Działa to świetnie podczas pracy z storyboardami. Możesz dodać widok wewnątrz scenorysu!
Jos Koomen
Działa też świetnie dla mnie. Byłoby wspaniale wspomnieć, że wartość zPosition powinna zostać ustawiona z powrotem na wartość 0 (wystarczy wspomnieć, że po zakończeniu należy ją ustawić ponownie). Mam także tabBar (z TabBarController na moim ekranie. Próbowałem ustawić zPosition, ale po powrocie do wartości tabBar nadal nie był widoczny. Więc dla tabBar lepiej użyć właściwości isHidden.
Libor Zapletal
1
Nie pracuj z ułatwieniami dostępu. Przesuwanie widoku nie spowoduje jego skupienia.
antonjn
Kocham Cię!! <3
chr0x
57

Szybkie wersje sprawdzonej odpowiedzi:

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)
Kevin ABRIOUX
źródło
6
Czy mogę ustawić tę osłonę na cały bieżący widok (kontroler widoku), ale pozostawić wyświetlany nad nią nowy kontroler widoku?
Michał Ziobro
24

Dodaj widok jako widok podrzędny NavigationController.

[self.navigationController.navigationBar addSubview: overlayView)]

Możesz także dodać go w oknie:

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

Mam nadzieję że to pomoże.. :)

Rashad
źródło
Nadchodzi widok, ale po dodaniu przycisku nie można było uzyskać akcji przycisku lub ustawić niestandardowego tekstu etykiety w widoku OverView
Vineesh TP
Działa dobrze dla mnie:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Arthur Clemens
22

Świetne rozwiązanie Dalef w szybkim:

self.navigationController?.view.addSubview(view)
Allreadyhome
źródło
11

Odpowiedź @ Nam działa świetnie, jeśli chcesz wyświetlić widok niestandardowy, ale jeśli widok niestandardowy wymaga interakcji użytkownika, musisz wyłączyć interakcję dlanavigationBar .

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

Jak powiedziano w odpowiedzi Nam, nie zapomnij cofnąć tych zmian:

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


Możesz to zrobić w lepszy sposób dzięki rozszerzeniu:

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

I po prostu użyj tego w następujący sposób:

self.navigationController.navigationBar.toggle()
Hemang
źródło
1
idealne rozwiązanie .. !! Próbowałem tyle rzeczy i spędziłem tyle czasu .. ale to działa dobrze .. !!
Dishant
8

Szybka wersja odpowiedzi @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
}

Nie zapominaj, że okno musi być silną właściwością, ponieważ oryginalna odpowiedź prowadzi do natychmiastowego zwolnienia okna

Jednostka iOS
źródło
6

Polecam utworzenie nowego interfejsu użytkownika:

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

Następnie możesz zarządzać swoim widokiem w innym UIViewController. Aby usunąć okna:

[window removeFromSuperview];
window = nil;

mam nadzieję, że to pomoże!

Nicolas Bonnet
źródło
3
Dzięki, ale myślę, że czegoś brakuje, ponieważ nic się nie pojawia: /
Nicolas Roy
6

Jest na to więcej niż jeden sposób:

1- Dodaj swoją UIViewna UIWindowzamiast dodawania go UIViewController. W ten sposób wszystko będzie na wierzchu.

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

2- Użyj niestandardowego przejścia, które sprawi, że Twój UIViewController będzie wyświetlać z tyłu 0,5 alfa

W tym celu polecam spojrzeć na to: https://github.com/Citrrus/BlurryModalSegue

Dani A.
źródło
4
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];
Jold
źródło
3

W Swift 4.2 i 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!)

W celu C

UIView * spinnerView; // To jest twój widok

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

Może to działać tylko w trybie pionowym lub poziomym.

Jeszcze jeden prosty kod to:

yourViewName.layer.zPosition = 1//Change you view name
iOS
źródło
2

Uwaga: jeśli chcesz dodać widok na pełnym ekranie, użyj tylko poniższego kodu

Dodaj te rozszerzenia z 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
      }
   }
}

Kontynuuj jak zwykły proces dodawania podglądu

Teraz użyj dodając viewDidAppear UIViewController

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

     self.makeViewAsFullScreen()
}
Paresh Navadiya
źródło
1

Użyłbym podklasy UIViewController zawierającej „Widok kontenera”, który osadza inne kontrolery widoku. Będziesz wtedy mógł dodać kontroler nawigacji do Widoku kontenera (na przykład używając segmentu relacji osadzania).

Zobacz Implementowanie kontrolera widoku kontenera

dulgan
źródło
1
UIApplication.shared.keyWindow?.insertSubview(yourView, at: 1)

Ta metoda działa z xcode 9.4, iOS 11.4

Ahmed R.
źródło
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];

wprowadź opis zdjęcia tutaj

Fadi Abuzant
źródło
0

Musisz dodać widok podrzędny do pierwszego okna z typem UITextEffectsWindow. Po pierwsze, ponieważ niestandardowe klawiatury dodają swoje UITextEffectsWindow, a jeśli dodasz do niego widok podrzędny, nie będzie to działać poprawnie. Nie można również dodać widoku podrzędnego do ostatniego okna, ponieważ na przykład klawiatura jest również oknem i nie można jej wyświetlić z okna klawiatury. Tak więc najlepszym rozwiązaniem, jakie znalazłem, jest dodanie widoku podrzędnego (lub nawet kontrolera widoku push) do pierwszego okna z typem UITextEffectsWindow, to okno obejmuje widok akcesoriów, pasek nawigacyjny - wszystko.

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)
Viktoria
źródło