Додайте UIView понад усе, навіть панель навігації


181

Я хочу відображати над будь-якими іншими видами, навіть навігаційною панеллю, такий вид "спливаючих" поглядів, який виглядає приблизно так:

  • повноекранний чорний фон з 0,5 альфа, щоб побачити інший UIViewControllerпід ним.
  • UIViewвікно в середині з деякою інформацією (календар , якщо ви хочете , щоб все знати).

Для цього я створив UIViewController, який містить два UIViews(фон і вікно), і я намагаюся його відобразити. Я спробував простий [mySuperVC addSubview:myPopUpVC.view], але у мене все ще є панель навігації вгорі.

Я намагався представити його як модальний, але UIViewControllerзнизу зникає, і я втрачаю ефект прозорості.

Будь-яка ідея зробити це, я впевнений, що це досить просто ...

Дякую!


Додайте підзор у вікно програми. Поводження із змінами орієнтації може бути хитромудрим: stackoverflow.com/questions/8774495/…
— Амарь

Відповіді:


197

Ви можете зробити це, додавши свій погляд безпосередньо до вікна key:

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

ОНОВЛЕННЯ - для Swift 4.1 і вище

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

2
Дякую :) На жаль, якщо ви перебуваєте в ландшафтному режимі, вам потрібно повернути вигляд. Я не впевнений, що знаю, як це правильно зробити.
— Ніколя Рой

Так, я перебуваю лише в ландшафтному режимі, і myView з'являється з обертанням на 90 градусів. Здається, це те, про що вони тут говорять: stackoverflow.com/questions/8774495/…
— Nicolas Roy

Проблема з орієнтацією трапляється на пристроях pre-iOS8, для яких це рішення, на жаль, не працює.
— thgc

@NicolasRoy Autolayout допоможе
— Дармен Аманбаєв

4
він не охоплює панель вкладок. Будь-яке рішення для цього?
— Маніша

134

[self.navigationController.view addSubview:overlayView]; це те, що ти справді хочеш


5
Вам потрібно встановити кадр
— Габріель Гонкальвес

1
Дуже вдале рішення, особливо, коли ви додаєте подання як "контролер дитячого перегляду"
— Річард Топчій,

2
Це не працює з поданням контролера дитячого перегляду. Зміна рівня z на рівні навігації (як пропонує Нам) також працює з контролерами дочірнього перегляду.
— Тапані

Це здається більш елегантним рішенням, ніж додавання перегляду до вікна Key. Оскільки це забезпечує додатковий вигляд, рухається вздовж анімації базового виду. Тому що якщо перегляд додано у вікні ключа, він не надходить з анімацією, і його потрібно видалити окремо, якщо ви хочете відхилити контролер.
— soan saini

це не надмірно спливаюче вікно, але це просто правильна річ для мого випадку. Спасибі))
— Dilshod Zopirov

112

Ось просте елегантне рішення, яке працює для мене. Ви можете встановити позицію z на панелі навігації внизу перегляду:

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

Просто не забудьте повернути його до 0, коли закінчите.


1
Це працює набагато краще, ніж додавання перегляду накладеного зображення як підвід до подання контролера навігації (що, до речі, викликає збій). Таке рішення z-позиції, ймовірно, набагато надійніше і спричиняє менше проблем у майбутньому.
— Тапані

Це чудово спрацьовує при роботі з розповідями. Ви можете додати вигляд всередині аркуша розкадри!
— Джос Коомен

Також чудово працює для мене. Було б чудово згадати, що zPosition має бути встановлено на значення 0 (ви просто зазначите, що він повинен бути повернутий після завершення). І у мене є tabBar (від TabBarController на моєму екрані теж. Я намагався встановити zPosition, але при поверненні до 0 значення tabBar ще не було видно. Тож для tabBar краще використовувати властивість isHidden.
— Libor Zapletal

1
Не працюйте з доступністю. Якщо панорамувати погляд, це не зосередить його.
— antonjn

Я тебе люблю!! <3
— chr0x

57

Швидкі версії для перевіреної відповіді:

Швидкий 4:

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

Швидкий 3.1:

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

6
Чи можу я зробити так, щоб ця панель охоплювала весь поточний вигляд (контролер перегляду), але залишала новий з'являється контролер подання відображається над ним?
— Michał Ziobro

24

Додайте вам уявлення як підвид перегляду NavigationController.

[self.navigationController.navigationBar addSubview: overlayView)]

Ви також можете додати його через вікно:

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

Сподіваюся, це допомагає .. :)


Наближається перегляд, але при додаванні кнопки не вдалося отримати дії кнопки або встановити власний текст мітки на OverView
— Vineesh TP,

Для мене добре працює:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
— Артур Клеменс


11

@ Відповідь Нама чудово працює, якщо ви просто хочете відобразити свій власний перегляд, але якщо ваш власний перегляд потребує взаємодії з користувачем, вам потрібно відключити взаємодію дляnavigationBar .

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

Як сказано у відповіді Нама, не забудьте змінити ці зміни:

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


Ви можете зробити це кращим чином за допомогою розширення:

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

І просто використовуйте його так:

self.navigationController.navigationBar.toggle()

1
ідеальне рішення .. !! Спробував стільки речей і витратив стільки часу .. але це прекрасно працює .. !!
— Дисант

8

Швидка версія відповіді @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
}

Не забувайте, що вікно повинно бути сильним властивістю, оскільки оригінальна відповідь призводить до негайного розстановки вікна


6

Я рекомендую вам створити нове вікно UIW:

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

Потім ви можете керувати своїм переглядом в іншому UIViewController. Щоб видалити вікна:

[window removeFromSuperview];
window = nil;

сподіваюся, що допоможе!


3
Дякую, але я думаю, що чогось не вистачає, тому що нічого не з’являється: /
— Nicolas Roy

6

Існує кілька способів зробити це:

1 Додайте свій UIViewна UIWindowзамість додавання його UIViewController. Таким чином він буде на вершині всього.

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

2- Використовуйте спеціальний перехід, який дозволить утримувати показ UIViewController іззаду з 0,5 альфа

Для цього я рекомендую подивитися на це: https://github.com/Citrrus/BlurryModalSegue



3

У Swift 4.2 та 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!)

У Objective C

UIView * spinnerView; // Це ваш погляд

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

Це може працювати лише в режимі «Портрет або АВТО».

Ще один простий код:

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

2

Зверніть увагу, якщо ви хочете додати перегляд на весь екран, тоді використовуйте лише код нижче

Додайте ці розширення в 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
      }
   }
}

Продовжуйте як звичайний процес додавання підперегляду

Тепер використовуйте для додавання перегляду UIViewControllerDidAppear

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

     self.makeViewAsFullScreen()
}

1

Я б використовував підклас UIViewController, що містить "Перегляд контейнерів", в який вбудовуються ваші інші контролери перегляду. Після цього ви зможете додати контролер навігації всередині перегляду контейнерів (наприклад, використовуючи відомість вбудовування зв'язку).

Див. Розділ Впровадження контролера перегляду контейнерів


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

Цей метод працює з 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];

введіть тут опис зображення


0

Вам потрібно додати підперегляд у перше вікно з типом UITextEffectsWindow. По-перше, оскільки спеціальні клавіатури додають своє UITextEffectsWindow, і якщо ви додасте до нього підвід, це не працюватиме належним чином. Крім того, ви не можете додати підпогляд до останнього вікна, тому що клавіатура, наприклад, також є вікном, і ви не можете бути присутніми у вікні клавіатури. Тож найкраще рішення, яке я знайшов, - додати підперегляд (або навіть натиснути контролер перегляду) до першого вікна з типом UITextEffectsWindow, це вікно охоплює подання з аксесуарами, навібар - все.

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.