UIView, его супервизор и касанияНачало:

Предположим, у меня есть подкласс UIViewController, который заботится о некоторых UIView. Эти UIView добавляются как подпредставления свойства view UIViewController):

UIViewController:

- (void)viewDidLoad {
    UIImageView *smallImageView...
    [self.view addSubview:smallImageView];

    UIButton *button..
    [self.view addSubview:button];

    UIView *bigUIView.. // covers the entire screen (frame = (0.0, 0.0, 1024.0, 768.0))
    [self.view addSubview:bigUIView];
...
}

Насколько я знаю, поскольку bigUIView является самым передним видом и покрывает весь экран, он получит touchesBegan:withEvent:, а другие виды, такие как button, не получат никаких событий касания.

В моем приложении bigUIView должно быть самым верхним представлением, потому что оно содержит основные объекты пользовательского интерфейса (на самом деле CALayers, основные игровые объекты), которые при анимации должны быть поверх всех других вторичных элементов пользовательского интерфейса (UIButtons и т. д.). Тем не менее, я хотел бы иметь UIButtons и другие объекты в цепочке респондентов.

Я попытался реализовать следующее в классе bigUIView:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    
    [self.superview touchesBegan:touches withEvent:event];

    ... hit test the touch for this specific uiview..
}

Примечания:

  1. Суперпредставление bigUIView относится к свойству view UIViewController, распространяет ли оно событие касания на все его подпредставления?
  2. bigUIView должен иметь userInteractionEnabled = YES, потому что он также обрабатывает пользовательский ввод.
  3. Я не могу вывести button/smallImageView на передний план, потому что они будут отображаться над основными игровыми объектами (подслоями bigUIView).

Заранее спасибо.


person Eduardo Coelho    schedule 07.02.2011    source источник


Ответы (2)


Попробуйте переопределить pointInside:withEvent: в классе bigUIView, чтобы вернуть NO, если точка находится внутри прямоугольника кадра одного из других подпредставлений фонового представления. Поскольку это родственный элемент этих других представлений, механизм проверки попадания продолжит тестирование других подпредставлений и найдет то, которое соответствует точке, которую коснулся пользователь.

Кроме того, рассмотрите возможность реализации методов фазы события (-touchesBegan:withEvent: и т. д.) в вашем подклассе UIViewController, а не в классе bigUIView. iOS вставляет контроллеры представления за их представлениями в цепочке респондентов, поэтому сообщения о событиях будут всплывать к контроллеру представления, если только одно из других подпредставлений (например, кнопка) не перехватит его. Затем контроллер представления может отправлять любые сообщения, которые вам нравятся, в любое из своих представлений.

person jlehr    schedule 07.02.2011
comment
Спасибо jlehr, pointInside:withEvent: это решение. Возвращая NO, когда точка находится внутри прямоугольника кадра одного из других подпредставлений, метод -touchesBegan:withEvent: bigUIView не вызывается, а действие button запускается. Обратите внимание, что это вызывает связь между bigUIView и button. Как я могу перехватить методы фазы события только в UIViewController, когда bigUIView покрывает весь экран? Создать другую сигнатуру метода в классе bigUIView и делегировать ее классу catch all UIViewController? - person Eduardo Coelho; 07.02.2011
comment
Нет, вообще не реализуйте методы фазы события в bigUIView. Таким образом, сообщения будут пересылаться вверх по цепочке респондентов, пока не достигнут объекта с переопределенной реализацией (например, UIButton или вашего пользовательского подкласса UIViewController). - person jlehr; 07.02.2011
comment
Что касается связывания, рассмотрите возможность реализации метода делегата в вашем контроллере представления, который экземпляр bigUIView может вызвать для принятия фактического решения. Таким образом, контроллер представления будет отвечать за вычисление того, какое представление получает сообщение, и связи вообще не будет. - person jlehr; 07.02.2011
comment
Хорошо, но что, если моему bigUIView нужны аргументы метода делегата -touchesBegan:withEvent: для правильной работы? Переопределение приведет к остановке цепочки респондентов. Предлагаете ли вы создать сигнатуры методов «сестра» другой фазы события и реализовать их в bigUIView (такие методы будут вызываться UIViewController)? - person Eduardo Coelho; 07.02.2011
comment
Один из вариантов — направить все сообщения о событиях касания через контроллер, а затем позволить контроллеру решить, что происходит в ответ (частично путем отправки сообщений в одно или несколько представлений). Другим вариантом может быть включение вызова [super touchesBegan:withEvent:] в конце каждого из переопределенных методов в bigUIView, что позволит сообщениям продолжаться вверх по цепочке респондента, чтобы они были получены как bigUIView, так и его контроллером. - person jlehr; 07.02.2011

Обычно в цепочке респондентов события передаются в суперпредставления, а не в подпредставления. В любом случае, я бы преобразовал точки в событиях в локальную систему координат кнопки, и если она нажмет, отправит действие контроллеру.

person MHC    schedule 07.02.2011
comment
Я ценю комментарий, это интересное решение. Однако я пытаюсь избежать сильной связи между bigUIView (который принадлежит игровому пакету (CALayers)) и другими элементами пользовательского интерфейса (созданными в IB). Спасибо - person Eduardo Coelho; 07.02.2011
comment
Без проблем. bigUIView по-прежнему не должен работать с другими элементами пользовательского интерфейса. Но я согласен, что решение jlehr кажется правильным! - person MHC; 07.02.2011