Додайте 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.