2016-01-03 30 views
6

Sto cercando di implementare una vista a scorrimento che scatta sui punti durante lo scorrimento di.UIScrollView snap-to-position durante lo scorrimento

Tutti i post qui ho visto circa lo snap a un punto "dopo" l'utente ha terminato di trascinare la pergamena. Voglio farlo scattare durante il trascinamento.

Finora ho questo per fermare l'inerzia dopo il trascinamento e funziona benissimo:

func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { 
     targetContentOffset.memory = scrollView.contentOffset 
} 

Ho provato a farlo, ma non funziona, se lo desideri:

var scrollSnapHeight : CGFloat = myScrollView.contentSize.height/10 

scrollViewDidScroll:

func scrollViewDidScroll(scrollView: UIScrollView) { 
    let remainder : CGFloat = scrollView.contentOffset.y % scrollSnapHeight 
    var scrollPoint : CGPoint = scrollView.contentOffset 
    if remainder != 0 && scrollView.dragging 
    { 
     if self.lastOffset > scrollView.contentOffset.y //Scrolling Down 
     { 
      scrollPoint.y += (scrollSnapHeight - remainder) 
      NSLog("scrollDown") 
     } 
     else //Scrolling Up 
     { 
      scrollPoint.y -= (scrollSnapHeight - remainder) 
     } 
     scrollView .setContentOffset(scrollPoint, animated: true) 
    } 
    self.lastOffset = scrollView.contentOffset.y; 
} 

risposta

5

Questo approccio abiliterà/disabiliterà la proprietà scrollEnabled di UIScrollView.

Quando scrollView scorre all'esterno del dato scrollSnapHeight, effettuare scrollEnabled in false. Ciò fermerà lo scorrimento. Quindi fare di nuovo abilitare lo scorrimento per il prossimo trascinamento.

extension ViewController: UIScrollViewDelegate { 

    func scrollViewDidScroll(scrollView: UIScrollView) { 

     if scrollView.contentOffset.y > lastOffset + scrollSnapHeight { 
      scrollView.scrollEnabled = false 
     } else if scrollView.contentOffset.y < lastOffset - scrollSnapHeight { 
      scrollView.scrollEnabled = false 
     } 
    } 

    func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { 

     guard !decelerate else { 
      return 
     } 

     setContentOffset(scrollView) 
    } 

    func scrollViewWillBeginDecelerating(scrollView: UIScrollView) { 

     setContentOffset(scrollView) 
    } 
} 

func setContentOffset(scrollView: UIScrollView) { 

    let stopOver = scrollSnapHeight 
    var y = round(scrollView.contentOffset.y/stopOver) * stopOver 
    y = max(0, min(y, scrollView.contentSize.height - scrollView.frame.height)) 
    lastOffset = y 

    scrollView.setContentOffset(CGPointMake(scrollView.contentOffset.x, y), animated: true) 

    scrollView.scrollEnabled = true 
} 
+0

Quando si prova questo, dopo lo snap, l'utente deve sollevare il dito, quindi iniziare a trascinare di nuovo. C'è un modo per fare senza sollevare ritocchi? – Gizmodo

+0

@gizmodo Non ho potuto capire. Scattare a posizione significa che gli utenti possono trascinare ma scrollview non scorrerà. Ora su quale evento vuoi far scorrere di nuovo lo scrollView? –

+0

@gizmodo Se si desidera eseguire lo snap dopo che l'utente interrompe il trascinamento di scrollView, http://stackoverflow.com/a/35197919/1378447 –

1

sottoclasse UIScrollView/UICollectionView

Questa soluzione non richiede si solleva il dito in modo da sganciare e funziona durante lo scorrimento. Se ne hai bisogno per lo scorrimento verticale e non per lo scorrimento orizzontale, basta scambiare le x con y.

Impostare snappoint all'offset del contenuto in cui si desidera che sia il centro dello snap.

Impostare snapOffset sul raggio intorno al punto in cui si desidera che si verifichi lo snap.

Se è necessario sapere se lo scrollView si è spezzato, è sufficiente controllare la variabile isSnapped.

class UIScrollViewSnapping : UIScrollView { 
    public var snapPoint: CGPoint? 
    public var snapOffset: CGFloat? 
    public var isSnapped = false 

    public override var contentOffset: CGPoint { 
     set { 
      if let snapPoint = self.snapPoint, 
       let snapOffset = self.snapOffset, 
       newValue.x > snapPoint.x - snapOffset, 
       newValue.x < snapPoint.x + snapOffset { 
       self.isSnapped = true 
       super.contentOffset = snapPoint 
      } 
      else { 
       self.isSnapped = false 
       super.contentOffset = newValue 
      } 
     } 
     get { 
      return super.contentOffset 
     } 
    } 
} 
Problemi correlati