web-dev-qa-db-ja.com

UIScrollViewページの変更の検出

ユーザーがページング対応のUIScrollViewでページを変更したときに通知を検出または取得する方法はありますか?

76
Pompair

UIScrollViewのデリゲートを実装します。 これ メソッドはあなたが探しているものです。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
18
Viraj

これを使用して、現在表示されているページを検出し、ページの変更時に何らかのアクションを実行します。

- (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:デリゲートメソッド内で上記を実行するのが最善です。

192

ページングが有効なスクロールビューでは、 scrollViewDidEndDecelerating を使用して、ビューがページに確定するタイミングを知ることができます(同じページである可能性があります)。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

scrollViewDidScrollはすべての動きで呼び出されます。また、ページングのコンテキストでは、ビューを使用して次のページに移動するのに十分なスクロールがあるかどうかを確認できます(その時点でドラッグが停止している場合)。

64
Ankur Badola

UIScrollViewDelegateの2つのメソッドを組み合わせてどうですか?

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
   }
}
33
Cullen SUN

ページ検出のためのグーグルでの最初の結果なので、私の意見ではより良い解決策でこれに答えなければなりませんでした。 (この質問が2年半前に尋ねられたとしても。)

ページ番号を追跡するためだけにscrollViewDidScrollを呼び出さないようにします。それはそれのような簡単な何かのための行き過ぎです。 scrollViewDidEndDeceleratingを使用すると動作し、ページの変更で停止します[〜#〜] but [〜#〜](そしてそれは大きいですが、 )ユーザーが通常よりも2倍速く画面をスワイプすると、scrollViewDidEndDeceleratingは1回だけ呼び出されます。ページ#2を処理せずに、ページ#1からページ#3に簡単に移動できます。

これは私にとって完全に解決しました:

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

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

これにより、ユーザーは上記のリスクなしに一度​​に1ページだけスワイプできます。

22
Segev

Swift 4

これを行う最良の方法は、scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)を使用することです。画面から指を離すとすぐにページングが発生するかどうかを予測できます。この例は、水平方向にページングするためのものです。

UIScrollViewDelegateを採用し、このメソッドを実装するオブジェクトにscrollView.delegateを割り当てることを忘れないでください。

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)


}
10
Doug Galante

これがSwiftの解決策です。

コードを実装するクラスでcurrentPageとpreviousPageの2つのプロパティを作成し、0に初期化します。

ScrollViewDidEndDragging(:willDecelerate :)およびscrollViewDidEndDecelerating(:scrollView :)からcurrentPageを更新します。

そして、scrollViewDidEndScrollingAnimation(_:scrollView :)のpreviousPageを更新します

    //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
           }
       }
   }
1
Rohit tomar

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
}
}
0
Hiren Panchal