Как передать сенсорное событие для просмотра, когда userInteractionEnabled = ДА?

У меня есть следующие настройки.

+- XXXCustomControl : UIControl -------+
| A                                    |
|   +- ContentView -------------------+|
|   |                                 ||
|   |  B                              ||
|   |                                 ||
|   +---------------------------------+|
+--------------------------------------+ 

XXXCustomControl, который является подклассом UIControl. Он содержит одно подпредставление с именем contentView типа UIView с размером, меньшим, чем область Control. Это представление имеет .userInteractionEnabled = YES;

Мне нужно, чтобы это свойство было установлено в YES, потому что горизонтальные прокрутки время от времени помещаются внутрь, и их нужно прокручивать. Если суперпредставление (в нашем случае представление контента не позволяет взаимодействовать с пользователем, оно наследуется у подпредставлений.) Но в то же время этот XXXCustomControl должен быть применим, когда он не содержит прокрутки в своем представлении контента не только в области А, но и в области Б.

Так что у меня здесь "конфликт интересов", потому что я либо

1) установите представление контента на userInteractionEnabled = NO, тогда я могу нажать на пустой элемент управления в области просмотра контента как в A, так и в B, но скролл-обзоры, которые я здесь поместу, не будут прокручиваться..

2) установите для представления содержимого значение userInteractionEnabled = YES но затем, если userInteractionEnabled = YES управления пуст, я могу только коснуться области A, чтобы вызвать событие касания.

Одна идея, которая пришла мне в голову, заключается в том, что я по умолчанию устанавливаю для свойства значение NO, а при заполнении contentView задаю для него значение yes. когда я очищаю contentView, я возвращаю свойству значение no. По сути, я хочу, чтобы для этого параметра всегда было установлено значение yes, а когда оно пустое, принудительно заставляет contentView передавать событие touchUpInside до своего суперпредставления.

Это возможно?

Ответ 1

Вы можете попробовать переопределить метод pointInside:withEvent: во внутреннем представлении. Это позволит вам возвращать NO, когда вы хотите перенаправить касания в супервизор:

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if( /* You have content, and you want to receive touches */){
        return YES;
    }else{
        return NO;
    }
}

Ответ 2

Вы можете подклассифицировать свое подвью и реализовать

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!touchedContent) {
        [[self nextResponder] touchesBegan:touches withEvent:event];
    } else {
        [super touchesBegan:touches withEvent:event];
    }
}

Ответ 3

Вы можете использовать другой UIView для "скрытия" подвью. * Подробности: этот UIView является подчиненным братом. он имеет тот же размер и положение вашего подсмотра с цветом фона четкого цвета.

* Объясните: новый UIView примет прикосновение и автоматически передаст его в супервизор.

Таким образом, не нужно подклассифицировать ваш subview - это решение для раскадровки.
Пожалуйста, попробуйте это. Получайте удовольствие!

Ответ 4

- Свифт

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    if <#condition#> { return true }
    else { return false }
}

Ответ 5

Используйте это в супер-представлении, не меняя код subviews (так как subviews могут быть введены из других фреймворков или контейнеров):

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *view = [super hitTest:point withEvent:event];
    if ([view isDescendantOfView:self])
    {
        NSLog(@"touched inside");
    }
    return view;
}

Ответ 6

Если вы хотите обработать событие из суперпредставления (XXXCustomControl в вашем случае) вместо внутреннего представления (ContentView в вашем случае), вы можете написать следующий быстрый код в своем суперпредставлении:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    guard let view = super.hitTest(point, with: event) else { return nil }
    if view.isDescendant(of: self) {
        // your custom logic
    }
    return view
}