2012-02-20 13 views
19

Estoy tratando de usar el nuevo scrollViewWillEndDragging: withVelocity: targetContentOffset: Llamada de delegado de UIScrollView en iOS 5 pero parece que no puedo obtenerlo para que realmente me responda correctamente. Estoy cambiando el valor de targetContentOffset-> x pero nunca termina siendo utilizado. Sé que el código se está ejecutando porque llegará a los puntos de interrupción en esa función. Incluso intenté establecer el valor de compensación en un número codificado para que supiera dónde terminaría pero nunca funciona.Paginación de UIScrollView personalizada con scrollViewWillEndDragging

¿Alguien ha podido usar esto correctamente y hacerlo funcionar? ¿Hay alguna otra llamada de delegado que deba implementarse para que esto funcione?

Aquí está mi código en caso de que alguien ve algo malo en ello:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 
{ 
    // goodOffsetX returns the contentOffset i want the scrollView to stop at 
    CGFloat goodOffsetX = [self _horizontalContentOffsetForTargetHorizontalContentOffset:(*targetContentOffset).x velocity:velocity.x]; 

    NSLog(@" "); 
    NSLog(@"scrollViewWillEndDragging"); 
    NSLog(@" velocity: %f", velocity.x); 
    NSLog(@" currentX: %f", scrollView.contentOffset.x); 
    NSLog(@" uikit targetX: %f", (*targetContentOffset).x); 
    NSLog(@" pagedX: %f", goodOffsetX); 

    targetContentOffset->x = goodOffsetX; 
} 
+2

¿Tiene usted '' pagingEnabled' establecido en YES' en esta vista de desplazamiento? –

+3

pagingEnabled está establecido en NO, los documentos dicen que debe establecerse en NO para que se llame a este delegado. También traté de configurar SÍ solo para patadas y no se llama como lo indica el documento, pero hay un registro de la consola que dice que no lo haga con pagingEnabled establecido en SÍ. – Alex

+0

Mi problema fue que lo estaba probando en un teléfono con iOS4. Además, ¿ha establecido la propiedad de delegado de UIScrollView? – Marc

Respuesta

49

Puede implementar la paginación de encargo con este código:

- (float) pageWidth { 
    return ((UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout).itemSize.width + 
    ((UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout).minimumInteritemSpacing; 
} 

- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView { 

    CGFloat pageWidth = self.collectionView.frame.size.width + 10 /* Optional Photo app like gap between images. Or use [self pageWidth] in case if you want the next page be also visible */; 

    _currentPage = floor((self.collectionView.contentOffset.x - pageWidth/2)/pageWidth) + 1; 

    NSLog(@"Dragging - You are now on page %i", _currentPage); 
} 

- (void) scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint*)targetContentOffset { 

    CGFloat pageWidth = self.collectionView.frame.size.width + 10; // [self pageWidth] 

    int newPage = _currentPage; 

    if (velocity.x == 0) { // slow dragging not lifting finger 
     newPage = floor((targetContentOffset->x - pageWidth/2)/pageWidth) + 1; 
    } 
    else { 
     newPage = velocity.x > 0 ? _currentPage + 1 : _currentPage - 1; 

     if (newPage < 0) 
      newPage = 0; 
     if (newPage > self.collectionView.contentSize.width/pageWidth) 
      newPage = ceil(self.collectionView.contentSize.width/pageWidth) - 1.0; 
    } 

    NSLog(@"Dragging - You will be on %i page (from page %i)", newPage, _currentPage); 

    *targetContentOffset = CGPointMake(newPage * pageWidth, targetContentOffset->y); 
} 

Por supuesto que hay que establecer pagingEnabled = NO. _currentPage es una clase iVar. Gracias a http://www.mysamplecode.com/2012/12/ios-scrollview-example-with-paging.html por señalar el camino correcto.

+6

Esta es la mejor solución que he encontrado por mucho que emula la implementación predeterminada (solo se desplaza una página a la vez, manejando cargas lentas, etc.) –

+2

Esto funciona, pero si el arrastre finaliza con una velocidad demasiado pequeña, se moverá demasiado despacio hacia la nueva página. ¿Alguna sugerencia sobre cómo solucionar eso? – skagedal

+13

Para responder a mi propia pregunta, configure self.scrollView.decelerationRate = UIScrollViewDecelerationRateFast y las cosas serán geniales. :) – skagedal

7

que era capaz de ejecutar una prueba rápida y conseguimos esto al fuego y hacer mi parada objeto como desee correctamente. Hice esto usando la siguiente prueba:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 
{ 
    targetContentOffset->x = scrollView.contentOffset.x - 10;  
} 

Parece que este método no es probable que el problema en su código, pero es más probable que su 'goodOffsetX' no calcula correctamente un valor válido para parar en .

3

Swift 2.2:

extension SomeCollectionViewController { 

    override func scrollViewWillBeginDragging(scrollView: UIScrollView) { 
     let pageWidth = Float(collectionView!.frame.size.width) 
     let xCurrentOffset = Float(collectionView!.contentOffset.x) 
     currentPage = floor((xCurrentOffset - pageWidth/2)/pageWidth) + 1 
    } 

    override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { 
     let pageWidth = Float(collectionView!.frame.size.width) 
     let targetXContentOffset = Float(targetContentOffset.memory.x) 
     let contentWidth = Float(collectionView!.contentSize.width) 

     var newPage = currentPage 
     if velocity.x == 0 { 
      newPage = floor((targetXContentOffset - pageWidth/2)/pageWidth) + 1 
     } else { 
      newPage = velocity.x > 0 ? currentPage + 1 : currentPage - 1 
      if newPage < 0 { 
       newPage = 0 
      } 
      if newPage > contentWidth/pageWidth { 
       newPage = ceil(contentWidth/pageWidth) - 1.0 
      } 
     } 
     targetContentOffset.memory.x = CGFloat(newPage * pageWidth) 
    } 
} 

que también utilizó el collectionView?.decelerationRate = UIScrollViewDecelerationRateFast según lo sugerido por @skagedal a mejorar la velocidad de la página.

6

SWIFT 3

Con una demo aquí https://github.com/damienromito/CollectionViewCustom

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

    let pageWidth = Float(itemWidth + itemSpacing) 
    let targetXContentOffset = Float(targetContentOffset.pointee.x) 
    let contentWidth = Float(collectionView!.contentSize.width ) 
    var newPage = Float(self.pageControl.currentPage) 

    if velocity.x == 0 { 
     newPage = floor((targetXContentOffset - Float(pageWidth)/2)/Float(pageWidth)) + 1.0 
    } else { 
     newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1) 
     if newPage < 0 { 
      newPage = 0 
     } 
     if (newPage > contentWidth/pageWidth) { 
      newPage = ceil(contentWidth/pageWidth) - 1.0 
     } 
    } 
    let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y) 
    targetContentOffset.pointee = point 
} 
+0

Vale la pena señalar, si tiene un recuadro superior o izquierdo, debe agregarse al valor del punto antes de ser asignado. – Sethmr

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

let pageWidth = Float(appWidth + itemSpacing) 
    let targetXContentOffset = Float(targetContentOffset.pointee.x) 
    var newPage = Float(currentPageIndex) 

    // I use this way calculate newPage: 
    newPage = roundf(targetXContentOffset/pageWidth); 

    //if velocity.x == 0 { 
    // newPage = floor((targetXContentOffset - Float(pageWidth)/2)/Float(pageWidth)) + 1.0 
    //} else { 
    // newPage = Float(velocity.x > 0 ? newPage + 1 : newPage - 1) 
    // if newPage < 0 { 
    //  newPage = 0 
    // } 
    // if (newPage > contentWidth/pageWidth) { 
    //  newPage = ceil(contentWidth/pageWidth) - 1.0 
    // } 
    //} 

    let targetOffsetX = CGFloat(newPage * pageWidth) 
    let point = CGPoint (x: targetOffsetX, y: targetContentOffset.pointee.y) 
    targetContentOffset.pointee = point 
} 
Cuestiones relacionadas