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!

Nicolas Roy
sumber
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)
ROM.
sumber
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

Dalef
sumber
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.

Nam
sumber
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)
Kevin ABRIOUX
sumber
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.. :)

Rashad
sumber
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
22

Dalef solusi hebat dalam cepat:

self.navigationController?.view.addSubview(view)
Rumah sudah siap
sumber
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()
Hemang
sumber
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

Unit iOS
sumber
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!

Nicolas Bonnet
sumber
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

Dani A
sumber
4
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];
Jold
sumber
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
iOS
sumber
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()
}
Paresh Navadiya
sumber
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

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

Metode ini bekerja dengan xcode 9.4, iOS 11.4

Ahmed R.
sumber
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

Fadi Abuzant
sumber
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)
Viktoria
sumber