Обнаружение изменения страницы UIScrollView - PullRequest
76 голосов
/ 11 марта 2011

Есть ли способ обнаружить или получить уведомление, когда пользователь изменяет страницу в UIScrollView с поддержкой подкачки?

Ответы [ 8 ]

192 голосов
/ 11 марта 2011

Используйте это, чтобы определить, какая страница отображается в данный момент, и выполнить некоторые действия при смене страницы:

- (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:.

63 голосов
/ 07 апреля 2012

В режиме прокрутки с включенной подкачкой вы можете использовать scrollViewDidEndDecelerating , чтобы узнать, когда представление настраивается на странице (может быть, на той же странице).

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

scrollViewDidScroll вызывается при каждом движении. А в контексте просмотра с включенным поиском можно найти, когда его достаточно прокрутить для перехода на следующую страницу (если перетаскивание остановлено в этой точке).

33 голосов
/ 19 ноября 2015

Как насчет объединения двух методов 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
   }
}
21 голосов
/ 16 декабря 2013

Первый результат в google для обнаружения страниц, поэтому мне пришлось ответить на это с лучшим решением, на мой взгляд.(даже если бы этот вопрос был задан два с половиной года назад.)

Я бы предпочел не звонить scrollViewDidScroll только для отслеживания номера страницы.Это излишество для чего-то простого.Использование scrollViewDidEndDecelerating работает и останавливается при смене страницы НО (и это большое но), если пользователь проведет по экрану в два раза быстрее, чем обычно, scrollViewDidEndDecelerating будет вызываться только один раз.Вы можете легко перейти со страницы № 1 на страницу № 3, не обрабатывая страницу № 2.

Это полностью для меня решило:

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

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

Таким образом, пользователь может провести только одну страницу навремя без риска, описанного выше.

18 голосов
/ 11 марта 2011

Реализация делегата UIScrollView. Этот метод - это то, что вы ищете.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
8 голосов
/ 27 марта 2018

Swift 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)


}
1 голос
/ 22 марта 2017

Вот быстрое решение для этого.

Создайте два свойства currentPage и previousPage в классе, в котором вы реализуете свой код, и инициализируйте их в 0.

Теперь обновите currentPage из scrollViewDidEndDragging (: willDecelerate :) и scrollViewDidEndDecelerating (: scrollView:).

А затем обновите предыдущую страницу в 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
           }
       }
   }
0 голосов
/ 26 октября 2018

Для 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
}
}
...