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

Прохождение через UIView под

У меня есть UIView с 4 кнопками на нем, а другой UIView поверх представления кнопок. Верхний вид сверху содержит UIImageView с UITapGestureRecognizer на нем.

Поведение, которое я пытаюсь создать, заключается в том, что когда пользователь нажимает UIImageView, он переключается между малым в нижнем правом углу экрана и анимацией, чтобы стать больше. Когда он большой, я хочу, чтобы кнопки в нижнем виде были отключены, а когда они маленькие, а в правом нижнем углу я хочу, чтобы штрихи были переданы кнопкам и чтобы они работали нормально. Я почти там, но я не могу получить штрихи, чтобы перейти к кнопкам, если я не отключу UserInteractions верхнего вида.

У меня это в моем initWithFrame: вид сверху:

// Add a gesture recognizer to the image view
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageTapped:)];
tapGestureRecognizer.cancelsTouchesInView = NO;
[imageView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

и я это мой метод imageTapped::

- (void) imageTapped:(UITapGestureRecognizer *) gestureRecognizer {
    // Toggle between expanding and contracting the image
    if (expanded) {
        [self contractAnimated:YES];
        expanded = NO;
        gestureRecognizer.cancelsTouchesInView = NO;
        self.userInteractionEnabled = NO;
        self.exclusiveTouch = NO;
    }
    else {
        [self expandAnimated:YES];
        expanded = YES;
        gestureRecognizer.cancelsTouchesInView = NO;
        self.userInteractionEnabled = YES;
        self.exclusiveTouch = YES;
    }
}

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

Если я установил self.userInteractionEnabled = YES в обоих случаях, изображение будет расширяться и сжиматься при касании, но кнопки никогда не получат прикосновений и действуют так, как будто отключены.

Есть ли прочь, чтобы изображение расширялось и сокращалось при касании, но для кнопок внизу отображались только штрихи, если изображение находится в сжатом состоянии? Я делаю что-то глупое здесь и пропуская что-то очевидное?

Я абсолютно безумен, пытаясь заставить это работать, поэтому любая помощь будет оценена,

Dave

UPDATE:

Для дальнейшего тестирования я переопределил методы touchesBegan: и touchesCancelled: и назвал их супер реализацией на моем представлении, содержащем UIImageView. С приведенным выше кодом touchesCancelled: никогда не вызывается и всегда вызывается touchesBegan:.

Итак, кажется, что представление получает штрихи, они просто не передаются в представление внизу.

UPDATE

Это из-за того, как работает цепочка ответчиков? Моя иерархия просмотров выглядит следующим образом:

VC - View1
     -View2
      -imageView1 (has tapGestureRecogniser)
      -imageView2
     -View3
      -button1
      -button2

Я думаю, что ОС сначала делает hitTest, поскольку говорит, что View2 находится впереди, поэтому он должен получить все касания, и они никогда не передаются в View3, если для параметра UserInteractions не установлено значение NO для View2, и в этом случае изображениеView1 также не может быть получено прикасается. Это как это работает, и есть ли способ, чтобы View2 прошел через него, касается View3?

4b9b3361

Ответ 1

UIGestureRecognizer - красная селедка, я думаю. В конце концов, чтобы решить эту проблему, я перепробовал метод pointInside:withEvent: моего UIView:

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

    if (CGRectContainsPoint(imageView.frame, point) || expanded) pointInside = YES;

    return pointInside;
}

Это приводит к тому, что представление захватывает все касания, если вы касаетесь либо imageView, либо если установлен его расширенный флаг. Если он не расширен, то только ловушки касания, если они находятся на imageView.

Возвращая NO, верхний уровень VC View запрашивает остальную часть своей иерархии представлений, ища хит.

Ответ 2

Выберите ваш View в Storyboard или XIB и...


enter image description here


Или в Свифте

view.isUserInteractionEnabled = false

Ответ 3

Посмотрите в протокол UIGestureRecognizerDelegate. В частности, gestureRecognizer:shouldReceiveTouch:

Вы захотите сделать каждый UIGestureRecognizer свойством вашего UIViewController,

// .h
@property (nonatomic, strong) UITapGestureRecognizer *lowerTap;

// .m
@synthesize lowerTap;

// When you are adding the gesture recognizer to the image view
self.lowerTap = tapGestureRecognizer

Убедитесь, что вы сделали свой UIViewController делегатом,

[self.lowerTap setDelegate: self];

Тогда у вас будет что-то вроде этого,

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (expanded && gestureRecognizer == self.lowerTap) {    
        return NO;
    }
    else {
        return YES;
    }
}

Конечно, это не точный код. Но это общая схема, которой вы хотели бы следовать.

Ответ 4

У меня есть другое решение. У меня есть две точки зрения, позвольте называть их CustomSubView, которые накладываются друг на друга, и они должны оба получать штрихи. Таким образом, у меня есть контроллер представления и пользовательский класс UIView, позвоните ему ViewControllerView, который я установил в конструкторе интерфейса, а затем добавил два представления, которые должны получить штрихи к этому представлению.

Итак, я перехватил штрихи в ViewControllerView, переписав hitTest:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    return self;
}

Затем я перезаписал в ViewControllerView:

- (void)touchesBegan:(NSSet *)touches
           withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    for (UIView *subview in [self.subviews reverseObjectEnumerator])
    {
        if ([subview isKindOfClass:[CustomSubView class]])
        {
            [subview touchesBegan:touches withEvent:event];
        }
    }
}

Сделайте то же самое с touchesMoved touchesEnded и touchesCancelled.

Ответ 5

@Magic Bullet Dave решение, но в Swift

Свифт 3

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    var pointInside = false
    if commentTextField.frame.contains(point) {
        pointInside = true
    } else {
        commentTextField.resignFirstResponder()
    }
    return pointInside
}

Я использую его в CameraOverlayView для ImagePickerViewController.cameraOverlay, чтобы дать пользователю возможность комментировать при съемке новой фотографии.

Ответ 6

// this is due to userInteractionEnabled deficiency: the flag stops traversal of subviews
@objc(YourObjcPrefixHereForXibAndStoryboardUseViewTransparentToTouch)
open class ViewTransparentToTouch: UIView
{
public var daisyView: UIView?
override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let hitView = super.hitTest(point, with: event)
    if hitView === self {
        return daisyView
    }
    return hitView // childView
}
}