iphone - Detectando el cambio de la página UIScrollView
objective-c ipad (7)
¿Qué le parece combinar dos métodos de UIScrollViewDelegate?
En scrollViewDidEndDragging(_:willDecelerate:)
, si se detiene de inmediato, hacemos el cálculo de la página; si está desacelerando, lo dejamos ir y será capturado por scrollViewDidEndDecelerating(_:)
.
El código se prueba con XCode versión 7.1.1, Swift versión 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
}
}
¿Hay alguna manera de detectar u obtener una notificación cuando el usuario cambia la página en un UIScrollView habilitado para paginación?
Aquí está la solución rápida para esto.
Haga dos propiedades currentPage y previousPage en la clase donde está implementando su código e inicialícelas en 0.
Ahora actualice currentPage desde scrollViewDidEndDragging ( : willDecelerate :) y scrollViewDidEndDecelerating ( : scrollView :).
Y luego actualiza previousPage en 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
}
}
}
En la vista de desplazamiento activada de paginación, puede usar scrollViewDidEndDecelerating para saber cuándo se establece la vista en una página (puede ser la misma página).
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
scrollViewDidScroll
se scrollViewDidScroll
en cada movimiento. Y en el contexto de la visualización habilitada de paginación puede usarse para encontrar cuándo se desplaza lo suficiente para pasar a la página siguiente (si el arrastre se detiene en ese punto).
Implemente el delegado de UIScrollView. This método es lo que estás buscando.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
Primer resultado en google para la detección de páginas, así que tuve que responder a esto con una mejor solución en mi opinión. (incluso si esta pregunta fue hecha hace 2 años y medio).
Preferiría no llamar a scrollViewDidScroll
solo para rastrear el número de página. Eso es una exageración por algo tan simple como eso. Usar scrollViewDidEndDecelerating
funciona y se detiene en un cambio de página PERO (y es un gran pero) si el usuario desliza en la pantalla dos veces más rápido de lo normal, scrollViewDidEndDecelerating
solo se llamará una vez. Puede pasar fácilmente de la página 1 a la página 3 sin procesar la página 2.
Esto lo resolvió completamente para mí:
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
scrollView.userInteractionEnabled = NO;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
//Run your code on the current page
scrollView.userInteractionEnabled = YES;
}
De esta forma, el usuario solo puede deslizar una página a la vez sin el riesgo descrito anteriormente.
Use esto para detectar qué página se está mostrando actualmente y realizar alguna acción en el cambio de página:
- (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;
}
}
Si es aceptable que solo reaccione al cambio de página una vez que el desplazamiento se haya detenido por completo, entonces sería mejor hacer lo anterior dentro del método scrollViewDidEndDecelerating:
delegate en lugar del método scrollViewDidScroll:
.
Swift 4
Encontré que la mejor manera de hacerlo es usando scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)
. Le permite predecir si habrá paginación tan pronto como levante su dedo de la pantalla. Este ejemplo es para paginación horizontalmente.
Recuerde asignar el objeto scrollView.delegate
al objeto que adopta UIScrollViewDelegate
e implementa este método.
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)
}