2012-02-20 7 views
19

Sto provando a utilizzare il nuovo scrollViewWillEndDragging: withVelocity: targetContentOffset: chiamata del delegato UIScrollView in iOS 5 ma non riesco a ottenere che risponda correttamente a me correttamente. Sto cambiando il valore targetContentOffset-> x ma non viene mai utilizzato. So che il codice è in esecuzione perché colpirà i breakpoint in quella funzione. Ho persino provato a impostare il valore di offset su un numero codificato in modo da sapere dove andrebbe a finire, ma non funziona mai.UIScrollView personalizzato paging con scrollViewWillEndDragging

Qualcuno è stato in grado di usarlo correttamente e farlo funzionare? C'è qualche altra chiamata delegata che deve essere implementata affinché funzioni?

Ecco il mio codice nel caso in cui qualcuno vede qualcosa che non va:

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

Ti hanno 'pagingEnabled' impostato a' affermativa a questa visione di scorrimento? –

+3

pagingEnabled è impostato su NO, i documenti dicono che deve essere impostato su NO per poter chiamare questo delegato. Ho anche provato a impostarlo su YES solo per kick e non viene chiamato come per i doc, ma c'è qualche logging della console che dice di non farlo con pagingEnabled impostato su YES. – Alex

+0

Il mio problema era che lo stavo testando su un telefono con iOS4. Inoltre, è stata impostata la proprietà delegato di UIScrollView? – Marc

risposta

49

È possibile implementare il paging personalizzato con questo codice:

- (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); 
} 

Naturalmente è necessario impostare pagingEnabled = NO. _currentPage è una classe iVar. Grazie a http://www.mysamplecode.com/2012/12/ios-scrollview-example-with-paging.html per indicare la strada giusta.

+6

Questa è la soluzione migliore che ho trovato di gran lunga che emula l'implementazione di default (solo scorrendo una pagina alla volta, gestendo rallentamenti, ecc.) –

+2

Questo funziona, ma se il trascinamento termina con una velocità troppo bassa, si muoverà troppo lentamente verso la nuova pagina. Qualche suggerimento su come risolverlo? – skagedal

+13

Per rispondere alla mia domanda, imposta self.scrollView.decelerationRate = UIScrollViewDecelerationRateFast e le cose andranno benissimo! :) – skagedal

7

sono stato in grado di eseguire un test rapido e ottenuto questo al fuoco e fare la mia fermata oggetto, se lo desideri correttamente. Ho fatto questo utilizzando il seguente test semplice:

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

Sembra che questo metodo è probabilmente non è il problema nel codice, ma è più probabile che il 'goodOffsetX' non è il calcolo correttamente un valore valido di fermarsi a .

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

ho anche usato il collectionView?.decelerationRate = UIScrollViewDecelerationRateFast come suggerito da @skagedal per migliorare la velocità pagina.

6

SWIFT 3

Con una demo qui 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 notare che, se si dispone di un margine superiore o sinistro, è necessario aggiungerlo al valore del punto prima di essere assegnato. – 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 
} 
Problemi correlati