Прохождение через прикосновения к UIViews внизу
у меня есть UIView С 4 кнопками на нем и еще один UIView на верхней части кнопки. Самый верхний вид содержит UIImageView С UITapGestureRecognizer на нем.
поведение, которое я пытаюсь создать, заключается в том, что когда пользователь нажимает UIImageView он переключается между тем, чтобы быть маленьким в нижнем правом углу экрана и анимацией, чтобы стать больше. Когда он большой, я хочу, чтобы кнопки на нижнем виде были отключены, а когда он маленький и в нижнем правом углу I хотите, чтобы прикосновения передавались к кнопкам и чтобы они работали как обычно. Я почти там, но я не могу получить прикосновения, чтобы пройти к кнопкам, если я не отключу 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 в обоих случаях изображение расширяется и сжимается при прикосновении, но кнопки никогда не получают прикосновений и действуют как будто отключены.
есть ли возможность заставить изображение расширяться и сжиматься при прикосновении, но для кнопок внизу получать только прикосновения, если изображение находится в сжатом состоянии? Я делаю что-то глупое здесь и что-то упускаю очевидно?
я совершенно схожу с ума, пытаясь заставить это работать, поэтому любая помощь будет оценена,
Дэйв
обновление:
для дальнейшего тестирования я отключил touchesBegan: и touchesCancelled: методы и вызвал их супер реализации на мой взгляд, содержащий UIImageView. С кодом выше,touchesCancelled: никогда не называется и то touchesBegan: всегда вызывается.
таким образом, казалось бы, что вид становится прикосновения, они просто не передаются на вид снизу.
обновление
это из-за того, как работает цепочка ответчика? Иерархия моего представления выглядит так:
VC - View1
-View2
-imageView1 (has tapGestureRecogniser)
-imageView2
-View3
-button1
-button2
я думаю, что ОС сначала делает hitTest, поскольку говорит, что View2 находится впереди, поэтому должен получить все прикосновения, и они никогда не передаются в View3, если userInteractions не установлен в NO для View2, и в этом случае imageView1 также не получает прикосновений. Есть это, как это работает, и есть ли способ для View2, чтобы пройти через его прикосновения к View3?
6 ответов:
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 верхнего уровня запрашивает остальную часть своей иерархии представлений, ища хит.
посмотреть в Протокол 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; } }конечно, это не точный код. Но это общая схема, которой вы хотели бы следовать.
у меня есть другое решение. У меня есть два мнения, назовем их
CustomSubViewкоторые перекрывались, и они оба должны получить прикосновения. Поэтому у меня есть контроллер вида и пользовательский класс UIView, давайте назовем егоViewControllerViewчто я установил в interface builder, то я добавил два вида, которые должны получить штрихи к этому виду.поэтому я перехватил прикосновения в
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]; } } }Do то же самое с
touchesMovedtouchesEndedиtouchesCancelled.
@Magic Bullet решение Дэйва, но в Swift
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, чтобы дать пользователю возможность комментировать во время съемки новой фотографии
// 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 } }

Comments