Добавьте UIView прежде всего, даже панель навигации

181

Я хочу отобразить поверх любых других видов, даже панели навигации, своего рода «всплывающее» представление, которое выглядит следующим образом:

  • полноэкранный черный фон с 0,5 альфа, чтобы увидеть другой UIViewControllerснизу.
  • UIViewокно в середине с некоторой информацией (календарь , если вы хотите , чтобы все знать).

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

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

Любая идея сделать это, я уверен, что это довольно просто ...

Спасибо!

Николас Рой
источник
Добавьте подпредставление в окне вашего приложения. Обработка изменений ориентации может быть сложной задачей: stackoverflow.com/questions/8774495/…
Amar

Ответы:

197

Вы можете сделать это, добавив свой вид непосредственно в keyWindow:

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/…
Николас Рой
Проблема ориентации возникает на устройствах до iOS8, для которых это решение, к сожалению, не работает.
thgc
@NicolasRoy Autolayout поможет
Дармен Аманбаев
4
это не покрывает панель вкладок. Любое решение для этого?
Маниша
134

[self.navigationController.view addSubview:overlayView]; это то, что вы действительно хотите

dalef
источник
5
Вам нужно установить рамку
Габриэль Гонсалвес
1
Очень хорошее решение, особенно, когда вы добавляете представление в качестве «дочернего контроллера представления»
Ричард Топчий
2
Это не работает с дочерним представлением контроллера представления. Изменение z-уровня панели навигации (как предполагает Nam) работает также с контроллерами дочерних представлений.
Тапани
Это выглядит как более элегантное решение, чем добавление вида в окно Key. Поскольку это обеспечивает добавленное представление, перемещается вдоль анимации основного представления. Потому что, если представление добавлено в ключевое окно, оно не сопровождается анимацией и должно быть удалено отдельно, если вы хотите отключить контроллер.
Соан Сайни
это не слишком всплывающее окно, но это как раз то, что нужно для моего случая. Спасибо))
Дилшод Зопиров
112

Вот простое элегантное решение, которое работает для меня. Вы можете установить z положение навигационной панели ниже вида:

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

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

Nam
источник
1
Это работает намного лучше, чем добавление вида наложения в качестве подпредставления к представлению контроллера навигации (что, кстати, вызывает сбой). Такое решение по z-позиции, вероятно, намного надежнее и в будущем вызывает меньше проблем.
Тапани
Это прекрасно работает при работе с раскадровками. Вы можете добавить представление внутри раскадровки!
Йос Коомен
Прекрасно работает для меня тоже. Было бы здорово упомянуть, что zPosition должно быть установлено обратно в значение 0 (вы просто отметили, что оно должно быть установлено обратно, когда закончите). И у меня есть tabBar (из TabBarController на моем экране тоже. Я пытался установить zPosition, но при возврате в 0 значение tabBar все еще не было видно. Поэтому для tabBar лучше использовать свойство isHidden.
Libor
1
Не работайте с доступностью. Панорамирование по виду не будет фокусировать его.
antonjn
Я тебя люблю!! <3
chr0x
57

Версии 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)
Кевин ABRIOUX
источник
6
Могу ли я сделать эту обложку для всего текущего вида (контроллера вида), но оставить над ним новый отображаемый контроллер вида?
Михал Зиобро
24

Добавьте свой вид как подпредставление NavigationController.

[self.navigationController.navigationBar addSubview: overlayView)]

Вы также можете добавить его через окно:

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

Надеюсь это поможет.. :)

Рашад
источник
Over view идет, но, когда добавить кнопку не удалось получить действие кнопки или установить пользовательский текст метки на overView
Vineesh TP
У меня отлично работает:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Артур Клеменс
22

Далеф отличное решение в Свифте:

self.navigationController?.view.addSubview(view)
Allreadyhome
источник
11

Ответ @ Nam отлично работает, если вы просто хотите отобразить свой пользовательский вид, но если ваш пользовательский вид требует взаимодействия с пользователем, вам нужно отключить взаимодействие для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()
Hemang
источник
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
}

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

Блок iOS
источник
6

Я рекомендую вам создать новое окно 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];

Затем вы можете управлять своим представлением в другом UIViewController. Чтобы удалить окна:

[window removeFromSuperview];
window = nil;

надеюсь, что это поможет!

Николас Боннет
источник
3
Спасибо, но я думаю, что чего-то не хватает, потому что ничего не появляется: /
Николас Рой
6

Существует несколько способов сделать это:

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

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

2- Используйте пользовательский переход, который будет показывать ваш UIViewController сзади с альфа 0,5

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

Дани А
источник
4
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];
jold
источник
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!)

В цели 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
IOS
источник
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
      }
   }
}

Продолжайте как обычно добавляя процесс subview

Теперь используйте при добавлении viewDidAppear UIViewController

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

     self.makeViewAsFullScreen()
}
Пареш Навадия
источник
1

Я бы использовал подкласс UIViewController, содержащий «представление контейнера», которое встраивает ваши контроллеры представления других. После этого вы сможете добавить контроллер навигации в представление «Контейнер» (например, с помощью перехода «вставка»).

См. Реализация контроллера представления контейнера

dulgan
источник
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, и если вы добавите в него подпредставление, это не будет работать правильно. Кроме того, вы не можете добавить подпредставление к последнему окну, потому что клавиатура, например, также является окном, и вы не можете представить ее из окна клавиатуры. Поэтому лучшее решение, которое я нашел, - это добавить подпредставление (или даже контроллер push-представления) в первое окно с типом 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)
Viktoria
источник