[objective-c] UIGestureRecognizer는 터치 이벤트 처리를 위해 하위보기를 차단합니다.
나는 이것이 어떻게 올바른 방법으로 수행되는지 알아 내려고 노력하고 있습니다. 나는 상황을 묘사하려고 노력했습니다.
을 UITableView
하위 뷰로 추가 하고 UIView
있습니다. UIView
있는 누르고 응답 pinchGestureRecognizer
하지만, 이렇게이 때 상기의 tableview 그 두 제스처에 반응이 중지 (여전히 와이프 반응).
다음 코드로 작동하도록 만들었지 만 분명히 좋은 솔루션이 아니며 더 나은 방법이 있다고 확신합니다. 이것은 UIView
(Superview)에 있습니다.
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if([super hitTest:point withEvent:event] == self) {
for (id gesture in self.gestureRecognizers) {
[gesture setEnabled:YES];
}
return self;
}
for (id gesture in self.gestureRecognizers) {
[gesture setEnabled:NO];
}
return [self.subviews lastObject];
}
답변
나는 매우 유사한 문제가 있었고이 질문에서 내 해결책 을 찾았습니다 . 요약하면, 자신을 대리인으로 설정 UIGestureRecognizer
한 다음 인식기가 터치를 처리하도록 허용하기 전에 대상보기를 확인하십시오. 관련 위임 방법은 다음과 같습니다.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
답변
하위보기에 대한 터치 이벤트 차단이 기본 동작입니다. 이 동작을 변경할 수 있습니다.
UITapGestureRecognizer *r = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(agentPickerTapped:)];
r.cancelsTouchesInView = NO;
[agentPicker addGestureRecognizer:r];
답변
자체 테이블 뷰가있는 드롭 다운 하위 뷰를 표시하고있었습니다. 결과적으로 touch.view
는 때때로 UITableViewCell
. 나는 그것이 내가 생각했던 서브 클래스인지 확인하기 위해 수퍼 클래스 (들)를 밟아야했다.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
UIView *view = touch.view;
while (view.class != UIView.class) {
// Check if superclass is of type dropdown
if (view.class == dropDown.class) { // dropDown is an ivar; replace with your own
NSLog(@"Is of type dropdown; returning NO");
return NO;
} else {
view = view.superview;
}
}
return YES;
}
답변
@Pin Shih Wang 답변을 구축하십시오 . 탭 제스처 인식기가 포함 된보기의 탭을 제외한 모든 탭은 무시됩니다. 모든 탭은 설정 한대로 정상적으로보기 계층으로 전달됩니다 tapGestureRecognizer.cancelsTouchesInView = false
. 다음은 Swift3 / 4의 코드입니다.
func ensureBackgroundTapDismissesKeyboard() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGestureRecognizer.cancelsTouchesInView = false
self.view.addGestureRecognizer(tapGestureRecognizer)
}
@objc func handleTap(recognizer: UIGestureRecognizer) {
let location = recognizer.location(in: self.view)
let hitTestView = self.view.hitTest(location, with: UIEvent())
if hitTestView?.gestureRecognizers?.contains(recognizer) == .some(true) {
// I dismiss the keyboard on a tap on the scroll view
// REPLACE with own logic
self.view.endEditing(true)
}
}
답변
한 가지 가능성은 제스처 인식기를 하위 클래스로 분류하고 (아직하지 않은 경우) 재정 의하여 -touchesBegan:withEvent:
각 터치가 제외 된 하위보기에서 시작되었는지 여부를 결정 -ignoreTouch:forEvent:
하고 그 경우 해당 터치를 호출 하도록 재정의 하는 것 입니다.
분명히 제외 된 하위보기 또는 제외 된 하위보기의 배열을 추적하려면 속성도 추가해야합니다.
답변
어떤 클래스도 상속하지 않고 할 수 있습니다.
제스처의 콜백 선택기에서 gestureRecognizers를 확인할 수 있습니다.
view.gestureRecognizers에 gestureRecognizer가 포함되어 있지 않으면 무시하십시오.
예를 들면
- (void)viewDidLoad
{
UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
singleTapGesture.numberOfTapsRequired = 1;
}
여기에서 view.gestureRecognizers 확인
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer
{
UIEvent *event = [[UIEvent alloc] init];
CGPoint location = [gestureRecognizer locationInView:self.view];
//check actually view you hit via hitTest
UIView *view = [self.view hitTest:location withEvent:event];
if ([view.gestureRecognizers containsObject:gestureRecognizer]) {
//your UIView
//do something
}
else {
//your UITableView or some thing else...
//ignore
}
}