2016-01-03 24 views
6

Próbuję zaimplementować widok przewijania, który jest przyciągany do punktów podczas przewijania.UIScrollWyłącz snap-to-position podczas przewijania

Wszystkie posty tutaj widziałem o przyciąganie do punktu "po" użytkownik zakończył przeciąganie przewijania. Chcę go przyciągnąć podczas przeciągania.

tej pory mam to zatrzymać bezwładność po przeciągnięciu i działa prawidłowo:

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

próbowałem tego, ale nie działa jako pożądanej:

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

Odpowiedz

5

To podejście włącza/wyłącza właściwość UIScrollView.

Gdy scrollView przewija poza podanym scrollSnapHeight, zmień scrollEnabled na false. To zatrzyma przewijanie. Następnie ponownie włącz przewijanie dla następnego przeciągania.

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

Kiedy próbuję tego, po przyciśnięciu, użytkownik musi podnieść palec w górę, a następnie rozpocząć przeciąganie ponownie. Czy istnieje sposób na zrobienie bez podnoszenia dotyku? – Gizmodo

+0

@ gadizm Nie mogłem zrozumieć. Przyciąganie do pozycji oznacza, że ​​użytkownicy mogą przeciągać, ale przewijanie nie będzie przewijane. Teraz, na którym wydarzeniu chcesz przewinąć scrollView ponownie? –

+0

@ gizmodo Jeśli chcesz zrobić przystawkę po zatrzymaniu użytkownika, przeciągnij scrollView, http://stackoverflow.com/a/35197919/1378447 –

1

podklasa UIScrollView/UICollectionView

To rozwiązanie nie wymaga podnieś palec w celu Odczep i pracuje podczas przewijania. Jeśli potrzebujesz go do przewijania w pionie, a nie do przewijania w poziomie, wymień X na y.

Ustaw snapPoint na przesunięcie treści tam, gdzie ma być środek przyciągania.

Ustaw snapOffset na promień wokół punktu, w którym ma nastąpić przyciąganie.

Jeśli potrzebujesz wiedzieć, czy scrollView został przyciągnięty, po prostu sprawdź zmienną 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 
     } 
    } 
}