Подтвердить что ты не робот

UIView. Почему субподъемы вне его родительского объема не получают прикосновения?

У меня есть простая тривиальная иерархия родительских/дочерних элементов UIView. Один родитель (UIView). Один ребенок (UIButton). Ограничения родителей меньше, чем ограничение на ребенка, так что часть ребенка выходит за пределы ограничивающей рамки его родителя.

Здесь проблема: те части дочернего элемента вне bbox родителя не получают штрихи. Только нажатие внутри bbox родителя позволяет дочерней кнопке получать штрихи.

Кто-нибудь может предложить исправление/обход?

UPDATE

Для тех, кто следит за этим вопросом, вот решение, которое я реализовал в результате @Bastians самый отличный ответ:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {

    BOOL isInside = [super pointInside:point withEvent:event];

    // identify the button view subclass
    UIButton *b = (UIButton *)[self viewWithTag:3232];
    CGPoint inButtonSpace = [self convertPoint:point toView:b];

    BOOL isInsideButton = [b pointInside:inButtonSpace withEvent:nil];

    if (isInsideButton) {

        return isInsideButton;

    } // if (YES == isInsideButton)

    return isInside;        
}
4b9b3361

Ответ 1

Проблема - цепочка респондентов. Когда вы прикасаетесь к экрану, он будет спускаться от родителей к ребенку.

Итак, когда вы касаетесь экрана, родитель увидит, что прикосновение находится за пределами его собственных границ, и поэтому дети даже не спросят.

Функция, которая делает это hitTest. Если у вас есть собственный класс UIView, вы можете перезаписать его и вернуть кнопку самостоятельно.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

Ответ 2

Per Явная документация, самый простой и надежный способ, которым я нашел это, - переопределить hitTest:withEvent: в суперклассе вашего обрезанный вид выглядит следующим образом:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    // Convert the point to the target view coordinate system.
    // The target view isn't necessarily the immediate subview
    CGPoint pointForTargetView = [self.targetView convertPoint:point fromView:self];

    if (CGRectContainsPoint(self.targetView.bounds, pointForTargetView)) {

        // The target view may have its view hierarchy,
        // so call its hitTest method to return the right hit-test view
        return [self.targetView hitTest:pointForTargetView withEvent:event];
    }

    return [super hitTest:point withEvent:event];
}

Ответ 3

Предварительное условие:

У вас есть UIButton (названный как button1) внутри UIView (именованный как контейнер), а кнопка1 частично находится за пределами границ контейнера.

Проблема

часть за пределами контейнера кнопки 1 не будет отклика клика.

Решение

подкласс вашего контейнера из UIView:

class Container: UIView {
    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {

        let closeButton = viewWithTag(10086) as! UIButton  //<-- note the tag value
        if closeButton.pointInside(convertPoint(point, toView: closeButton), withEvent: event) {
            return true
        }
        return super.pointInside(point, withEvent: event)
    }
}

Не забудьте указать свой тэг button1 10086

Ответ 4

У меня была такая же проблема. Вам нужно только переопределить:

- (BOOL) pointInside: (CGPoint) point withEvent: (UIEvent *) событие

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

@implementation ARQViewToRightmost

// We should not need to override this one !!!
/*-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if ([self isInside:point])
        return self;
    return nil;
}*/

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if ([self isInside:point])
        return YES; // That answer will make hitTest continue recursively probing the view subviews for hit
    return NO;
}

// Check to see if the point is within the bounds of the view. We've extended the bounds to the max right
// Make sure you do not have any other sibling UIViews to the right of this one as they will never receive events
- (BOOL) isInside:(CGPoint)point
{
    CGFloat maxWidth = CGFLOAT_MAX;
    CGRect rect = CGRectMake(0, 0, maxWidth, self.frame.size.height);
    if (CGRectContainsPoint(rect, point))
        return YES;
    return NO;
}

@end