UIView.Почему A Subviews вне пределов своего родителя не получает штрихи? - PullRequest
36 голосов
/ 01 мая 2011

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

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

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

ОБНОВЛЕНИЕ

Для тех, кто задает этот вопрос, вот решение, которое я реализовал в результате самого превосходного ответа @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;        
}

Ответы [ 5 ]

25 голосов
/ 01 мая 2011

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

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

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

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
4 голосов
/ 30 августа 2014

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

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

    // Convert the point to the target view's 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];
}
2 голосов
/ 15 февраля 2018
  • @ Дугла, спасибо за вопрос!
  • @ Бастиан и @laoyur, спасибо тебе за ответы!

Swift 4

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {

    if yourChildView.point(inside: convert(point, to: yourChildView), with: event) {
        return true
    }

    return super.point(inside: point, with: event)
}
2 голосов
/ 21 декабря 2016

Условие :

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

Проблема :

часть вне контейнера кнопки 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

0 голосов
/ 04 июня 2013

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

- (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's 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
...