[ios] UIScrollView가 스크롤을 완료 한 시점을 감지하는 방법

UIScrollViewDelegate에는 두 가지 대리자 메서드 scrollViewDidScroll:scrollViewDidEndScrollingAnimation:있지만 스크롤이 완료되면 두 가지 중 어느 것도 알려주지 않습니다. scrollViewDidScroll스크롤보기가 스크롤을 완료하지 않았다는 것을 알려줍니다.

다른 방법 scrollViewDidEndScrollingAnimation은 사용자가 스크롤하지 않고 프로그래밍 방식으로 스크롤보기를 이동하는 경우에만 발생하는 것으로 보입니다.

누구든지 스크롤보기가 스크롤을 완료했을 때 감지하는 구성표를 알고 있습니까?



답변

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self stoppedScrolling];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        [self stoppedScrolling];
    }
}

- (void)stoppedScrolling {
    // ...
}


답변

(320) 구현은 훨씬 더 있습니다 – 여기 스크롤의 일관성을 시작 / 끝을 얻을 수있는 패치입니다.

-(void)scrollViewDidScroll:(UIScrollView *)sender
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
    //ensure that the end of scroll is fired.
    [self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:sender afterDelay:0.3];

...
}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
...
}


답변

scrollViewDidEndDecelerating이 원하는 것 같습니다. UIScrollViewDelegates 선택적 메소드 :

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

스크롤보기가 스크롤 이동 감속을 종료했음을 대리인에게 알립니다.

UIScrollViewDelegate 문서


답변

상호 작용 드래그와 관련된 모든 스크롤에 충분합니다.

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    _isScrolling = NO;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        _isScrolling = NO;
    }
}

이제 스크롤이 프로그래밍 방식의 setContentOffset / scrollRectVisible 때문인 경우 ( animated= YES 또는 스크롤이 종료 된 시점을 분명히 알 수 있음) :

 - (void)scrollViewDidEndScrollingAnimation {
     _isScrolling = NO;
}

스크롤이 키보드 열기 또는 키보드 닫기와 같은 다른 것으로 인한 경우 scrollViewDidEndScrollingAnimation유용하지 않기 때문에 해킹으로 이벤트를 감지 해야하는 것처럼 보입니다 .

PAGINATED 스크롤보기 의 경우 :

애플은 가속 곡선을 적용하고 scrollViewDidEndDecelerating드래그 할 때마다 호출되므로이 scrollViewDidEndDragging경우 사용할 필요가 없다고 생각합니다 .


답변

이것은 다른 답변 중 일부에서 설명되었지만 스크롤이 완료되었을 때 결합 scrollViewDidEndDecelerating하고 scrollViewDidEndDragging:willDecelerate일부 작업을 수행 하는 방법은 다음 과 같습니다 (코드) .

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self stoppedScrolling];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
                  willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [self stoppedScrolling];
    }
}

- (void)stoppedScrolling
{
    // done, do whatever
}


답변

: 난 단지 거의 같은 내가 요구되는이 질문에 발견 단지
있는 UIScrollView의 스크롤이 정지했을 때 정확히 어떻게 알 수 있습니까?

스크롤 할 때 didEndDecelerating이 작동하지만 고정 릴리스로 이동하면 등록되지 않습니다.

결국 해결책을 찾았습니다. didEndDragging의 매개 변수는 WillDecelerate이며 고정 해제 상황에서는 false입니다.

didEndDecelerating과 함께 DidEndDragging에서! decelerate를 확인하면 스크롤이 종료되는 두 가지 상황이 발생합니다.


답변

Rx를 사용하는 경우 다음과 같이 UIScrollView를 확장 할 수 있습니다.

import RxSwift
import RxCocoa

extension Reactive where Base: UIScrollView {
    public var didEndScrolling: ControlEvent<Void> {
        let source = Observable
            .merge([base.rx.didEndDragging.map { !$0 },
                    base.rx.didEndDecelerating.mapTo(true)])
            .filter { $0 }
            .mapTo(())
        return ControlEvent(events: source)
    }
}

다음과 같이 할 수 있습니다.

scrollView.rx.didEndScrolling.subscribe(onNext: {
    // Do what needs to be done here
})

이것은 드래그와 감속을 모두 고려합니다.