programing

UIScrollView 페이지 변경 감지

nasanasas 2020. 10. 15. 07:53
반응형

UIScrollView 페이지 변경 감지


사용자가 페이징이 활성화 된 UIScrollView에서 페이지를 변경할 때 알림을 감지하거나받는 방법이 있습니까?


UIScrollView의 대리자를 구현하십시오. 방법은 당신이 찾고있는 것입니다.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

이를 사용하여 현재 표시되는 페이지를 감지하고 페이지 변경에 대한 몇 가지 조치를 수행하십시오.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    static NSInteger previousPage = 0;
    CGFloat pageWidth = scrollView.frame.size.width;
    float fractionalPage = scrollView.contentOffset.x / pageWidth;
    NSInteger page = lround(fractionalPage);
    if (previousPage != page) {
        // Page has changed, do your thing!
        // ...
        // Finally, update previous page
        previousPage = page;
    }
}

스크롤이 완전히 중지 된 후에 만 ​​페이지 변경에 반응하는 것이 허용되는 경우 scrollViewDidEndDecelerating:메서드 대신 델리게이트 메서드 내에서 위의 작업을 수행하는 것이 가장 좋습니다 scrollViewDidScroll:.


페이징이 활성화 된 스크롤보기에서 scrollViewDidEndDecelerating사용 하여보기가 페이지 (동일한 페이지 일 수 있음)에 정착 된시기를 알 수 있습니다.

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

scrollViewDidScroll모든 움직임에서 호출됩니다. 그리고 페이징의 맥락에서 사용 가능한 뷰는 다음 페이지로 이동할 수있을만큼 스크롤 될 때를 찾는 데 사용할 수 있습니다 (그 지점에서 드래그가 중지 된 경우).


UIScrollViewDelegate의 두 가지 방법을 결합하는 것은 어떻습니까?

에서는 scrollViewDidEndDragging(_:willDecelerate:)즉시 중지되면 페이지 계산을 수행합니다. 감속 중이면 놓아두면 scrollViewDidEndDecelerating(_:).

코드는 XCode 버전 7.1.1, Swift 버전 2.1에서 테스트되었습니다.

class ViewController: UIViewController, UIScrollViewDelegate {

  // MARK: UIScrollViewDelegate
  func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if decelerate == false {
        let currentPage = scrollView.currentPage
        // Do something with your page update
        print("scrollViewDidEndDragging: \(currentPage)")
    }
  }

  func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    let currentPage = scrollView.currentPage
    // Do something with your page update
    print("scrollViewDidEndDecelerating: \(currentPage)")
  }

}

extension UIScrollView {
   var currentPage: Int {
      return Int((self.contentOffset.x+ (0.5*self.frame.size.width))/self.frame.width)+1
   }
}

페이지 감지를 위해 Google에서 첫 번째 결과를 얻었으므로 내 의견으로는 더 나은 솔루션으로 대답해야했습니다. (이 질문이 2 년 반 전에 요청 된 경우에도 마찬가지입니다.)

scrollViewDidScroll페이지 번호를 추적 하기 위해 전화를 걸고 싶지 않습니다 . 그것은 단순한 것에 대한 과잉입니다. 사용하여 scrollViewDidEndDecelerating작업을 수행하고 페이지 변화를 중지 하지만 (그리고 그것은 큰입니다 만) 사용자가 두 번 조금 더 빨리 평소보다 화면에 슬쩍 않을 경우 scrollViewDidEndDecelerating한 번만 호출됩니다. 2 페이지를 처리하지 않고도 1 페이지에서 3 페이지로 쉽게 이동할 수 있습니다.

이것은 나를 위해 완전히 해결되었습니다.

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    scrollView.userInteractionEnabled = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //Run your code on the current page
    scrollView.userInteractionEnabled = YES;
}

이렇게하면 사용자는 위에서 설명한 위험없이 한 번에 한 페이지 만 스 와이프 할 수 있습니다.


스위프트 4

이 작업을 수행하는 가장 좋은 방법은 scrollViewWillEndDragging(_:withVelocity:targetContentOffset:). 화면에서 손가락을 떼 자마자 페이징이 발생할지 예측할 수 있습니다. 이 예제는 수평 페이징을위한 것입니다.

이 메서드 scrollView.delegate를 채택 UIScrollViewDelegate하고 구현 하는 객체에를 할당해야합니다 .

var previousPageXOffset: CGFloat = 0.0

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    let targetOffset = targetContentOffset.pointee

    if targetOffset.x == previousPageXOffset {
        // page will not change
    } else if targetOffset.x < previousPageXOffset {
        // scroll view will page left
    } else if targetOffset.x > previousPageXOffset {
        // scroll view will page right
    }

    previousPageXOffset = targetOffset.x
    // If you want to track the index of the page you are on just just divide the previousPageXOffset by the scrollView width.
    // let index = Int(previousPageXOffset / scrollView.frame.width)


}

Here is the swift solution for this.

Make two properties currentPage and previousPage in the class where you are implementing your code and initialize them to 0.

Now update currentPage from scrollViewDidEndDragging(:willDecelerate:) and scrollViewDidEndDecelerating(:scrollView:).

And then update previousPage in scrollViewDidEndScrollingAnimation(_:scrollView:)

    //Class Properties
    var currentPage = 0
    var previousPage = 0

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        updatePage(scrollView)
        return
    }

 func scrollViewDidEndDecelerating(scrollView: UIScrollView){
        updatePage(scrollView)
        return
    }


 func updatePage(scrollView: UIScrollView) {
        let pageWidth:CGFloat = scrollView.frame.width
        let current:CGFloat = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1
        currentPage = Int(current)

        if currentPage == 0 {
              // DO SOMETHING
        }
        else if currentPage == 1{
              // DO SOMETHING

        }
    }

func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
     if previousPage != currentPage {
          previousPage = currentPage
          if currentPage == 0 {
              //DO SOMETHING
             }else if currentPage == 1 {
               // DO SOMETHING
           }
       }
   }

For Swift

static var previousPage: Int = 0
func scrollViewDidScroll(_ scrollView: UIScrollView){
let pageWidth: CGFloat = scrollView.frame.width
let fractionalPage: CGFloat = scrollView.contentOffset.x / pageWidth
let page = lround(Double(fractionalPage))
if page != previousPage
{
  print(page)
  // page changed
}
}

참고URL : https://stackoverflow.com/questions/5272228/detecting-uiscrollview-page-change

반응형