Gibt es eine Möglichkeit, eine Benachrichtigung zu erkennen oder zu erhalten, wenn der Benutzer die Seite in einer Paging-fähigen UIScrollView ändert?
77
Gibt es eine Möglichkeit, eine Benachrichtigung zu erkennen oder zu erhalten, wenn der Benutzer die Seite in einer Paging-fähigen UIScrollView ändert?
Verwenden Sie diese Option, um festzustellen, welche Seite gerade angezeigt wird, und führen Sie beim Seitenwechsel eine Aktion aus:
- (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; } }
Wenn es für Sie akzeptabel ist, erst dann auf den Seitenwechsel zu reagieren, wenn der Bildlauf vollständig gestoppt ist, ist es am besten, die obigen Schritte innerhalb der
scrollViewDidEndDecelerating:
Delegate-Methode anstelle derscrollViewDidScroll:
Methode auszuführen.quelle
scrollViewDidEndDecelerating
ist eine bessere, aber keine vollständige Lösung. Ich habe eine eigene Lösung hinzugefügt, die das Problem für mich vollständig gelöst hat.In der paging-fähigen Bildlaufansicht können Sie scrollViewDidEndDecelerating verwenden, um festzustellen , wann die Ansicht auf einer Seite festgelegt ist (möglicherweise dieselbe Seite).
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
scrollViewDidScroll
wird bei jeder Bewegung aufgerufen. Im Zusammenhang mit Paging kann die aktivierte Ansicht verwendet werden, um festzustellen, wann ein Bildlauf durchgeführt wurde, um zur nächsten Seite zu gelangen (wenn das Ziehen an diesem Punkt gestoppt wird).quelle
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
und- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
überhaupt nicht aufgerufen werden?Wie wäre es mit der Kombination von zwei Methoden von UIScrollViewDelegate?
In
scrollViewDidEndDragging(_:willDecelerate:)
, wenn es sofort aufhört, machen wir die Seite Berechnung; Wenn es langsamer wird, lassen wir es los und es wird von gefangenscrollViewDidEndDecelerating(_:)
.Der Code wird mit XCode Version 7.1.1, Swift Version 2.1 getestet
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 } }
quelle
Das erste Ergebnis bei Google zur Seitenerkennung, daher musste ich dies meiner Meinung nach mit einer besseren Lösung beantworten. (Auch wenn diese Frage vor zweieinhalb Jahren gestellt wurde.)
Ich würde es vorziehen, nicht nur anzurufen
scrollViewDidScroll
, um die Seitenzahl zu verfolgen. Das ist ein Overkill für so etwas Einfaches. Die VerwendungscrollViewDidEndDecelerating
funktioniert und stoppt auf einer Seite, ABER (und es ist ein großes, aber), wenn der Benutzer zweimal etwas schneller als normal über den Bildschirm wischt,scrollViewDidEndDecelerating
wird nur einmal aufgerufen. Sie können problemlos von Seite 1 zu Seite 3 wechseln, ohne Seite 2 zu verarbeiten.Das hat es für mich komplett gelöst:
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { scrollView.userInteractionEnabled = NO; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { //Run your code on the current page scrollView.userInteractionEnabled = YES; }
Auf diese Weise kann der Benutzer jeweils nur eine Seite ohne das oben beschriebene Risiko streichen.
quelle
scrollViewWillBeginDecelerating
hineinstecken, werden Sie feststellen, dass der Benutzer in der Sekunde, in der der Benutzer seinen Finger vom ersten Wischen hebt, diesen Haltepunkt erreicht.Swift 4
Ich fand den besten Weg, dies zu tun, ist mit
scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)
. Sie können vorhersagen, ob Paging auftreten wird, sobald Sie Ihren Finger vom Bildschirm heben. Dieses Beispiel dient zum horizontalen Blättern.Denken Sie daran, das
scrollView.delegate
dem Objekt zuzuweisen , dasUIScrollViewDelegate
diese Methode übernimmt und implementiert.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) }
quelle
Hier ist die schnelle Lösung dafür.
Machen Sie zwei Eigenschaften currentPage und previousPage in der Klasse, in der Sie Ihren Code implementieren, und initialisieren Sie sie mit 0.
Aktualisieren Sie jetzt currentPage von scrollViewDidEndDragging ( : willDecelerate :) und scrollViewDidEndDecelerating ( : scrollView :).
Und aktualisieren Sie dann die vorherige Seite 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 } } }
quelle
Ausschneiden und Einfügen für 2019
Das ist nicht so einfach:
var quantumPage: Int = -100 { // the UNIQUELY LANDED ON, NEVER REPEATING page didSet { print(">>>>>> QUANTUM PAGE IS \(quantumPage)") pageHasActuallyChanged() // your function } } private var possibleQuantumPage: Int = -100 { didSet { if oldValue != possibleQuantumPage { quantumPage = possibleQuantumPage } } } public func scrollViewDidEndDragging( _ scrollView: UIScrollView, willDecelerate decelerate: Bool) { if decelerate == false { possibleQuantumPage = currentPageEvenIfInBetween } } public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { possibleQuantumPage = currentPageEvenIfInBetween } var currentPageEvenIfInBetween: Int { return Int((self.contentOffset.x + (0.5 * self.frame.width)) / self.frame.width) }
Funktioniert perfekt.
pageHasActuallyChanged
wird nur aufgerufen, wenn der Benutzer Seiten wechselt, was Menschen als "Seitenwechsel" betrachten würden.Seien Sie sich bewusst: Das Aufrufen ist schwierig:
Dies ist zum Zeitpunkt des Starts schwierig zu initialisieren und hängt davon ab, wie Sie das ausgelagerte System verwenden .
In jedem ausgelagerten System haben Sie höchstwahrscheinlich so etwas wie "scrollToViewAtIndex ..."
open func scrollToViewAtIndexForBringup(_ index: Int) { if index > -1 && index < childViews.count { let w = self.frame.size.width let h = self.frame.size.height let frame = CGRect(x: CGFloat(index)*w, y: 0, width: w, height: h) scrollRectToVisible(frame, animated: false) // NOTE THE FALSE // AND IMPORTANTLY: possibleQuantumPage = currentPageEvenIfInBetween } }
Wenn der Benutzer das "Buch" auf Seite 17 öffnet, rufen Sie in Ihrer Bossklasse diese Funktion auf, um es beim Aufrufen auf "17" zu setzen.
In einem solchen Beispiel , würden Sie müssen nur daran denkendass Sie müssen zunächst unsere possibleQuantumPage Wert in solchen bringup Funktionen eingestellt; Es gibt keinen wirklich verallgemeinerten Weg, um mit der Ausgangssituation umzugehen.
Schließlich möchten Sie vielleicht nur "schnell" zur Startseite scrollen und wer weiß, was das in einer quantumPage-Situation "bedeutet". Stellen Sie daher sicher, dass Sie Ihr Quantenseitensystem während des Startvorgangs entsprechend Ihrer Situation sorgfältig initialisieren.
Kopieren Sie auf jeden Fall einfach die fünf Funktionen oben und fügen Sie sie ein, um ein perfektes Quanten-Paging zu erhalten.
quelle
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 } }
quelle
var scrollViewPage = 0 override func viewDidLoad() { super.viewDidLoad() scrollViewPage = scrollView.currentPage } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { if scrollViewPage != scrollView.currentPage { scrollViewPage = scrollView.currentPage // Do something with your page update print("scrollViewDidEndDecelerating: \(scrollViewPage)") } }
Und Erweiterung verwenden
extension UIScrollView { var currentPage: Int { return Int((self.contentOffset.x + (0.5 * self.frame.size.width)) / self.frame.width) + 1 } }
quelle