Tambahkan UIView di atas segalanya, bahkan bilah navigasi


181

Saya ingin menampilkan, di atas tampilan lain, bahkan bilah navigasi, sejenis tampilan "pop-up" yang terlihat seperti ini:

  • layar penuh latar belakang hitam dengan 0,5 alpha untuk melihat yang lain di UIViewControllerbawahnya.
  • sebuah UIViewjendela di tengah dengan beberapa informasi, (kalender jika Anda ingin tahu segalanya).

Untuk melakukan itu, saya telah membuat UIViewController yang berisi keduanya UIViews(latar belakang dan jendela), dan saya mencoba untuk menampilkannya. Saya sudah mencoba yang sederhana [mySuperVC addSubview:myPopUpVC.view], tetapi saya masih memiliki bilah navigasi di atas.

Saya sudah mencoba menyajikannya sebagai modal, tetapi di UIViewControllerbawahnya menghilang, dan saya kehilangan efek transparansi saya.

Ada ide untuk melakukan ini, saya yakin itu cukup sederhana ...

Terima kasih!


Tambahkan subview di jendela aplikasi Anda. Menangani perubahan orientasi bisa rumit: stackoverflow.com/questions/8774495/…
Amar

Jawaban:


197

Anda dapat melakukannya dengan menambahkan tampilan Anda langsung ke keyWindow:

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

UPDATE - Untuk Swift 4.1 ke atas

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

2
Terima kasih :) Sayangnya jika Anda dalam mode lansekap Anda perlu memutar tampilan. Saya tidak yakin saya tahu bagaimana melakukannya dengan benar.
Nicolas Roy

Ya, saya hanya dalam mode lansekap dan myView muncul dengan rotasi 90 derajat. Tampaknya apa yang mereka bicarakan di sini: stackoverflow.com/questions/8774495/…
Nicolas Roy

Masalah orientasi terjadi pada perangkat pra-iOS8, yang sayangnya solusi ini tidak berfungsi.
thgc

@NicolasRoy Autolayout akan membantu
Darmen Amanbayev

4
itu tidak mencakup bilah tab. Ada solusi untuk itu?
Manisha

134

[self.navigationController.view addSubview:overlayView]; adalah apa yang Anda inginkan


5
Anda perlu mengatur bingkai
Gabriel Goncalves

1
Solusi yang sangat baik, terutama, ketika Anda menambahkan tampilan sebagai "pengontrol tampilan anak"
Richard Topchii

2
Ini tidak berfungsi dengan tampilan pengontrol tampilan anak. Mengubah z-level bilah navigasi (seperti yang disarankan Nam) juga berfungsi dengan pengontrol tampilan anak.
Tapani

Tampaknya solusi yang lebih elegan daripada menambahkan tampilan ke jendela Key. Karena hal ini memastikan tampilan yang ditambahkan, bergerak di sepanjang animasi tampilan dasar. Karena jika tampilan ditambahkan pada jendela kunci, itu tidak disertai dengan animasi dan harus dihapus secara terpisah jika Anda ingin mengabaikan pengontrol.
soan saini

itu tidak lebih dari popup tetapi itu hal yang tepat untuk kasus saya. Terima kasih))
Dilshod Zopirov

112

Berikut adalah solusi elegan sederhana yang berfungsi untuk saya. Anda dapat mengatur posisi z bilah navigasi ke bawah tampilan:

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

Hanya ingat untuk mengaturnya kembali ke 0 setelah selesai.


1
Ini berfungsi lebih baik daripada menambahkan tampilan overlay sebagai subview ke tampilan controller navigasi (yang omong-omong menyebabkan crash). Solusi posisi-z ini mungkin jauh lebih dapat diandalkan dan menyebabkan lebih sedikit masalah di masa depan.
Tapani

Ini bekerja sangat baik ketika bekerja dengan storyboard. Anda dapat menambahkan tampilan di dalam storyboard!
Jos Koomen

Berfungsi bagus untuk saya juga. Akan bagus untuk menyebutkan bahwa zPosition harus diatur kembali ke nilai 0 (Anda hanya menyebutkan bahwa itu harus diatur kembali ketika selesai). Dan saya memiliki tabBar (dari TabBarController di layar saya juga. Saya mencoba mengatur zPosition tetapi ketika kembali ke nilai 0 tabBar masih belum terlihat. Jadi untuk tabBar lebih baik menggunakan properti isHidden.
Libor Zapletal

1
Jangan bekerja dengan aksesibilitas. Panning atas tampilan tidak akan fokus.
antonjn

Aku cinta kamu!! <3
chr0x

57

Versi cepat untuk respons yang diperiksa:

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
Dapatkah saya membuat ini mencakup semua tampilan saat ini (pengontrol tampilan), tetapi membiarkan pengontrol tampilan baru ditampilkan di atasnya?
Michał Ziobro

24

Tambahkan tampilan Anda sebagai subview dari NavigationController.

[self.navigationController.navigationBar addSubview: overlayView)]

Anda juga dapat menambahkannya di jendela:

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

Semoga ini membantu.. :)


Over view akan datang tetapi, ketika menambahkan tombol tidak bisa mendapatkan tindakan tombol atau mengatur teks label kustom pada overView
TP

Bekerja dengan baik untuk saya:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Arthur Clemens


11

@ Nam's answer berfungsi dengan baik jika Anda hanya ingin menampilkan tampilan khusus Anda tetapi jika tampilan khusus Anda memerlukan interaksi pengguna, Anda perlu menonaktifkan interaksi untuknavigationBar .

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

Seperti yang dikatakan dalam jawaban Nam jangan lupa untuk membalikkan perubahan ini:

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


Anda dapat melakukan ini dengan cara yang lebih baik dengan ekstensi:

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

Dan cukup gunakan seperti ini:

self.navigationController.navigationBar.toggle()

1
solusi sempurna .. !! Sudah mencoba banyak hal dan menghabiskan banyak waktu .. tapi ini bekerja dengan baik .. !!
Dishant

8

Versi cepat jawaban @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
}

Jangan lupa bahwa jendela itu haruslah properti yang kuat, karena jawaban aslinya mengarah ke deallokasi jendela dengan segera


6

Saya sarankan Anda untuk membuat UIWindow baru:

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

Kemudian Anda dapat mengelola tampilan Anda di UIViewController lainnya. Untuk menghapus windows:

[window removeFromSuperview];
window = nil;

berharap itu akan membantu!


3
Terima kasih, tapi saya pikir ada sesuatu yang hilang karena tidak ada yang muncul: /
Nicolas Roy

6

Ada lebih dari satu cara untuk melakukannya:

1- Tambahkan UIViewpada UIWindowbukannya menambahkan pada UIViewController. Dengan cara ini akan berada di atas segalanya.

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

2- Gunakan transisi khusus yang akan membuat UIViewController Anda ditampilkan di belakang dengan 0,5 alpha

Untuk itu saya sarankan Anda melihat ini: https://github.com/Citrrus/BlurryModalSegue


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

3

Di Swift 4.2 dan 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!)

Dalam Tujuan C

UIView * spinnerView; // Ini adalah pandangan Anda

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

Ini hanya bisa berfungsi mode Portrait atau Landscape.

Satu lagi kode sederhana adalah:

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

2

Catatan jika Anda ingin menambahkan tampilan dalam layar penuh maka hanya gunakan kode di bawah ini

Tambahkan ekstensi ini dari 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
      }
   }
}

Lanjutkan seperti biasa menambahkan proses subview

Sekarang gunakan dalam menambahkan viewDidAppear UIViewController's

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

     self.makeViewAsFullScreen()
}

1

Saya akan menggunakan subkelas UIViewController yang berisi "Tampilan Kontainer" yang menyematkan pengendali tampilan orang lain. Anda kemudian dapat menambahkan pengontrol navigasi di dalam Tampilan Kontainer (misalnya dengan menggunakan hubungan sematan embed).

Lihat Menerapkan Pengendali Tampilan Kontainer


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

Metode ini bekerja dengan 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];

masukkan deskripsi gambar di sini


0

Anda perlu menambahkan subview ke jendela pertama dengan tipe UITextEffectsWindow. Ke yang pertama, karena keyboard khusus menambahkan UITextEffectsWindow mereka, dan jika Anda menambahkan subview, ini tidak akan berfungsi dengan benar. Selain itu, Anda tidak dapat menambahkan subview ke jendela terakhir karena keyboard, misalnya, juga merupakan jendela dan Anda tidak dapat hadir dari jendela keyboard. Jadi solusi terbaik yang saya temukan adalah menambahkan subview (atau bahkan push view controller) ke jendela pertama dengan tipe UITextEffectsWindow, jendela ini mencakup tampilan aksesori, navbar - segalanya.

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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.