2010-06-29 2 views
0

다음과 같은 문제로 고민하고 있습니다. 스크롤 뷰가있는보기 컨트롤러가 있습니다. 이 스크롤 뷰를 사용하면 사용자는 사과의 날씨 앱과 같이 흔히 볼 수있는 '페이지'세트를 스 와이프 할 수 있어야합니다. 그런 다음 스크롤보기 내의 각 "페이지"는 항목 목록을 보여주는 테이블보기입니다. 그리고 여기에 문제가 생겼습니다.응답기 체인에서 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에 의해 이벤트 처리가 어떻게 구현되는지 설명 할 수 있다면 충분할 것입니다.

의견을 보내 주셔서 감사합니다.

답변

0

기본적으로 테이블보기에서는 세로 스크롤을 원하지만 가로 스 와이프에서는 페이징을 원하십니까? UISwipeGestureRecognizer를 사용하고 테이블보기 이 추가 - - 표준 구성 요소없이 멋진 추가 처리 스틱 - 을하는 경우 : 당신이 3.2 이상 호환성을 살 수 있다면

(실제로 아이폰 4.0), 나는 시도 것 제스처 인식기가 실행되면 가로 스 와이프인지 확인하고 프로그래밍 방식으로 페이지로 변경합니다.

물론 모든 개념은 셀에서 스 와이프 동작이 필요하지 않은 경우에만 작동합니다. 그러나 이것은 물론 모든 접근법에 유효합니다.

3.2 이전에는 터치 핸들러로 손을 젖게해야했습니다. UITableView를 서브 클래 싱하고 touchesBegan : 등등을 오버 라이딩합니다. 전체 솔루션이 추악하기는하지만 처음 시도 (가로 스 와이프를 인식하고 페이징 호출) 할 수 있습니다.

+0

의견을 보내 주셔서 감사합니다. Eiko,하지만 불행히도 앱은 3.0 이상이 호환되어야합니다. 그래서 나는 그 물건을 망설입니다. 나는 touchesBegan을 구현하려고 시도했다 : ... and co. UITableView, UIScrollView 및 UIViewController의 사용자 정의 하위 클래스에서는 아직까지 운이 없었습니다.UIScrollView 문서에서는 타이머를 사용하여 수평/수직 제스처 인식을 추가하는 것을 제외하고 기본적으로 수행해야하는 기본 서브 뷰에 패스 터치를 '드래그'해야하는지 확인합니다. UIScrollView에서 어떻게 구현되는지 궁금합니다! – Matthes

관련 문제