Отключить взаимодействие с окном iOS

У меня на экране два UIWindows и один за другим. есть ли способ обработать прикосновение пользователя к окну, которое находится позади?

Спасибо


person Ponja    schedule 28.10.2014    source источник


Ответы (4)


Вы должны просто отключить его, как и любой UIView.

UIWindow *secondWindow = [[UIWindow alloc] initWithFrame:<#frame#>];
[secondWindow setUserInteractionEnabled:NO];
person Ryan Poolos    schedule 28.10.2014
comment
Это будет означать, что ни верхнее окно, ни окно позади не будут получать никаких событий взаимодействия с пользователем, верно? - person jboi; 06.09.2016
comment
Я так не думаю. Если вы отключите взаимодействие с пользователем, он не съедает прикосновения, а скорее игнорирует их. Так что ваши прикосновения должны отбрасывать его к окну под ним. - person Ryan Poolos; 06.09.2016

iOS по умолчанию сначала смотрит, к какому окну прикоснулись, если в сенсорной области находится несколько окон, она выбирает верхнее (на основе уровня окна, индекса z)

затем он вызовет hitTest(_ point: CGPoint, with event: UIEvent) -> UIView? в окне, которое, по мнению ОС, было затронуто.

Если ваши представления в этом окне могут вернуть nil (в этом окне нельзя коснуться представления или вы переопределили hitTest), тогда окно вернет его само.

Чтобы решить эту проблему, вам нужно создать подкласс UIWindow и переопределить функцию hitTest. Если представление, возвращенное из super.hitTest_:with:), равно нулю или self // the window, вы можете делегировать его другому окну. Обратите внимание на тот факт, что окно, к которому вы прикоснулись, может иметь другое координатное пространство, чем окно, которому вы делегируете полномочия.

Пример:

internal final class CustomWindow: UIWindow {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if let view = super.hitTest(point, with: event), view != self {
            return view
        }

        guard let keyWindow = UIApplication.shared.keyWindow else {
            return nil
        }

        return keyWindow.hitTest(keyWindow.convert(point, from: self), with: event)
    }
}
person Saren Inden    schedule 18.05.2018
comment
Осторожно, это не будет работать в ios 13, так как в UIWindow будут вставлены некоторые самые верхние приватные представления, которые будут ловить касания, а super.hitTest вернет эти приватные представления. - person Alfred Zien; 11.10.2019

Спасибо, но я только что нашел способ:

  - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
  {
      for (UIWindow *win  in [[UIApplication sharedApplication] windows]) {
          if (win.tag != self.tag) {
              return [win hitTest:point withEvent:event];
          }
      }
      return nil;
  }
person Ponja    schedule 28.10.2014

Вы сможете принимать сенсорные события только на одном UIWindow за раз. UIWindow, который принимает события, называется keyWindow.

[behindWindow makeKeyAndVisible];

Ваш передний план UIWindow останется видимым, но ваш behindWindow будет получать события.

person Ian MacDonald    schedule 28.10.2014
comment
Но тогда только ключевое окно могло получать взаимодействие с пользователем, верно? Что делать, если у меня есть элементы пользовательского интерфейса в обоих окнах, которые требуют взаимодействия? - person jboi; 06.09.2016
comment
Вы можете одновременно принимать сенсорные события только в одном окне. Всегда есть ключевое окно: это единственное окно, которое принимает сенсорные события. Используя метод, показанный в этом ответе, вы указываете системе использовать другое ключевое окно. - person Ian MacDonald; 06.09.2016
comment
передние окна продолжают получать события - person user2387149; 07.10.2016
comment
@user2387149 user2387149 Как я уже говорил в своем ответе (и в ответе на комментарий), вы сможете принимать сенсорные события только на одном UIWindow за раз. - person Ian MacDonald; 07.10.2016
comment
@IanMacDonald вы можете иметь два отдельных окна и получать сенсорные события в обоих из них одновременно, даже если в качестве ключевого окна остается только 1: stackoverflow .com/a/34835333/4833705 - person Lance Samaria; 25.07.2020
comment
@LanceSamaria Да, это правда (и мне очень нравится ответ), но это решение делает несколько прыжков, чтобы это произошло. При нормальной работе только ключевое окно наблюдает за событиями. - person Ian MacDonald; 26.07.2020
comment
Вы правы, есть пара обручей, но, честно говоря, процесс занимает около 10 минут. У него были все эти дополнительные функции для перемещения кнопки по углам, добавления ее в делегат приложения и т. д. Без всех этих дополнительных функций все просто. В любом случае удачного кодирования!!! - person Lance Samaria; 26.07.2020