다음과 같은 문제로 고민하고 있습니다. 스크롤 뷰가있는보기 컨트롤러가 있습니다. 이 스크롤 뷰를 사용하면 사용자는 사과의 날씨 앱과 같이 흔히 볼 수있는 '페이지'세트를 스 와이프 할 수 있어야합니다. 그런 다음 스크롤보기 내의 각 "페이지"는 항목 목록을 보여주는 테이블보기입니다. 그리고 여기에 문제가 생겼습니다.응답기 체인에서 UITouch 이벤트를 올바르게 전달하는 방법은 무엇입니까?
스크롤보기가 모든 터치를 가로 채서 사용자가 손가락을 움직 였는지 또는 일부 하위보기 내에서 일부 지점을 탭했는지 확인하고 이동을 인식 할 경우 이벤트를 하위보기 (또는 수퍼 뷰)로 전달하지 않습니다.
테이블 뷰가 스크롤 뷰의 자손이며 정상적인 상황에서 히트 테스트에서 반환 된 뷰이므로 모든 경우에 발생하는 실제 문제 (스크롤 뷰 내의 테이블 뷰)가 발생합니다. 테이블 뷰에 의해 잡혀서 부모 스크롤 뷰 get은 결코 호출되지 않습니다. 따라서 스 와이프가 수행되지 않습니다.
본질적으로 테이블 뷰의 서브 클래스에서 hitTest : withEvent : 메소드를 오버라이드하고 실제로 슈퍼 뷰 (스크롤 뷰)를 반환하면 상황이 반대가됩니다. 사용자는 페이지를 스 와이프 할 수 있지만 테이블 뷰를 스크롤 할 수는 없습니다.
그래서 어떤 수준에서 - 사용자가 취하려고하는 작업 (테이블보기를 위 또는 아래로 스 와이프 또는 스크롤)을 결정한 다음 적절한 구성 요소로 이벤트 흐름을 전달하는 방법을 알아야합니다.
지금이 문제로 며칠 씩 싸우고 있지만 끝내지는 못합니다. 아래는 지금까지 내가 끝낸 것입니다. 아주 간단합니다. 그것은 내가 필요로하는 거의 무엇입니까 - 표보기가 절대로 스크롤되는 것을 제외하고 ... 내 테이블보기 하위 클래스는 항상 스크롤보기 self.superview를 반환합니다 유의하십시오.
/// UIViewController
- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event {
[super touchesBegan: touches withEvent: event];
/// Save initial touch location for later use
_motionStart = [[touches anyObject] locationInView: self.scrollView];
/// Save reference to initial event
_initialEvent = event;
/// Fire timer
_gestureTimer = [NSTimer scheduledTimerWithTimeInterval: 0.2
target:self selector:@selector(gestureTimer:)
userInfo: touches repeats: NO];
}
- (void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event {
if(!_gestureTimer && !_forwardingTouchesToTableView) {
/// If no timer is running and no event forwarding is performed, pass to super
[super touchesMoved: touches withEvent: event];
}
else {
/// Pass event to currently visible tableview
[self.scrollView.centerPage touchesMoved: touches withEvent: event];
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded: touches withEvent: event];
if(_forwardingTouchesToTableView) {
[self.scrollView.centerPage touchesEnded: touches withEvent: event];
}
/// Reset state
_motionStart = CGPointZero;
_forwardingTouchesToTableView = NO;
}
- (void) gestureTimer: (NSTimer *) timer {
_gestureTimer = nil;
NSSet *touches = (NSSet *)timer.userInfo;
UITouch *touch = (UITouch *)[touches anyObject];
CGPoint currentTouchLocation = [touch locationInView: self.scrollView];
float deltaX = fabs(_motionStart.x - currentTouchLocation.x);
float deltaY = fabs(_motionStart.y - currentTouchLocation.y);
if(deltaY >= 4.0 && deltaX <= 12.0) {
/// Vertical move, forward to tableview
[self.scrollView cancelTouches];
_forwardingTouchesToTableView = YES;
[self.scrollView.centerPage touchesBegan: touches withEvent: _initialEvent];
_initialEvent = nil;
}
else {
/// Horizontal swipe - just reset state
_initialEvent = nil;
_forwardingTouchesToTableView = NO;
}
}
솔직히 말하면, 나는 다음에 무엇을 해야할지 모르겠다. 내가 찾은이 문제에 대한 몇 가지 해결책을 시도했지만 그들 중 누구도 실제로 일하지 않았습니다. 나는 이것에 대한 조언이나 조언을 매우 높이 평가할 것이다. 누군가 UIScrollView 또는 UITableView에 의해 이벤트 처리가 어떻게 구현되는지 설명 할 수 있다면 충분할 것입니다.
의견을 보내 주셔서 감사합니다.
의견을 보내 주셔서 감사합니다. Eiko,하지만 불행히도 앱은 3.0 이상이 호환되어야합니다. 그래서 나는 그 물건을 망설입니다. 나는 touchesBegan을 구현하려고 시도했다 : ... and co. UITableView, UIScrollView 및 UIViewController의 사용자 정의 하위 클래스에서는 아직까지 운이 없었습니다.UIScrollView 문서에서는 타이머를 사용하여 수평/수직 제스처 인식을 추가하는 것을 제외하고 기본적으로 수행해야하는 기본 서브 뷰에 패스 터치를 '드래그'해야하는지 확인합니다. UIScrollView에서 어떻게 구현되는지 궁금합니다! – Matthes