2011-10-27 13 views
17

W jaki sposób utworzyć dwa widoki przewijania, śledząc kolejne przewijanie?Tworzenie dwóch widoków UIScroll śledzić każdy inny sposób przewijania

Na przykład, mam widok przewijania (A) po lewej stronie ekranu, którego zawartość może przewijać w górę iw dół, ale nie w lewo i w prawo. Widok przewijania B odpowiada górze i dół litery A, ale można go również przewijać w lewo i w prawo. Widok przewijania A jest zawsze na ekranie.

----------------------------------------------------------- 
|    |           | 
|    |           | 
|    |           | 
|  A  |     B      | 
|    |           | 
| scrolls |           | 
| up & down |    scrolls all directions  | 
|    |           | 
----------------------------------------------------------- 

Jak robię to więc w górę iw dół przewijanie (z obu widzenia) również sprawia, drugi zwój widok w tym samym kierunku góra-dół? Czy istnieje inna metoda to zrobić?

Odpowiedz

39

Ustaw delegata przewijania widoku A być kontroler widok ... wtedy ...

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    CGPoint offset = scrollViewB.contentOffset; 
    offset.y = scrollViewA.contentOffset.y; 
    [scrollViewB setContentOffset:offset]; 
} 

Jeśli chcesz śledzić zarówno do siebie, a następnie ustawić delegata dla nich obu i użytkowania. ..

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    if([scrollView isEqual:scrollViewA]) { 
    CGPoint offset = scrollViewB.contentOffset; 
    offset.y = scrollViewA.contentOffset.y; 
    [scrollViewB setContentOffset:offset]; 
    } else { 
    CGPoint offset = scrollViewA.contentOffset; 
    offset.y = scrollViewB.contentOffset.y; 
    [scrollViewA setContentOffset:offset]; 
    } 
} 

powyższe można refactored jest metoda, która zaczyna się w dwóch scrollviews i odpowiada jeden do drugiego.

- (void)matchScrollView:(UIScrollView *)first toScrollView:(UIScrollView *)second { 
    CGPoint offset = first.contentOffset; 
    offset.y = second.contentOffset.y; 
    [first setContentOffset:offset]; 
} 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    if([scrollView isEqual:scrollViewA]) { 
    [self matchScrollView:scrollViewB toScrollView:scrollViewA]; 
    } else { 
    [self matchScrollView:scrollViewA toScrollView:scrollViewB]; 
    } 
} 

Swift 3 Wersja:

func scrollViewDidScroll(_ scrollView: UIScrollView) { 
     if scrollView == scrollViewA { 
      self.synchronizeScrollView(scrollViewB, toScrollView: scrollViewA) 
     } 
     else if scrollView == scrollViewB { 
      self.synchronizeScrollView(scrollViewA, toScrollView: scrollViewB) 
     } 
    } 

    func synchronizeScrollView(_ scrollViewToScroll: UIScrollView, toScrollView scrolledView: UIScrollView) { 
     var offset = scrollViewToScroll.contentOffset 
     offset.y = scrolledView.contentOffset.y 

     scrollViewToScroll.setContentOffset(offset, animated: false) 
    } 
+0

Awesome - to tylko zaoszczędziło mi sporo czasu ... –

+0

Czy możesz mi zaproponować przewijanie z inną prędkością –

+0

Wielkie dzięki! To oszczędzało mi tyle czasu. :) – nithinreddy

1

Próbowałem odpowiedź Simon Lee na iOS 11. To działało, ale nie bardzo dobrze. Dwa widoki przewijania zostały zsynchronizowane, ale używając tej metody, widoki przewijania utraciłyby efekt bezwładności (gdy nadal przewija się po zwolnieniu palca) i efekt odbicia. Myślę, że to ze względu na fakt, że ustawienie contentOffset poprzez setContentOffset(offset, animated: false) metody powoduje cykliczne wywołań metoda scrollViewDidScroll(_ scrollView: UIScrollView) delegata (patrz this question)

Oto rozwiązanie, które pracował dla mnie na iOS 11:

// implement UIScrollViewDelegate method 
    func scrollViewDidScroll(_ scrollView: UIScrollView) { 
     if scrollView == self.scrollViewA { 
      self.syncScrollView(self.scrollViewB, toScrollView: self.scrollViewA) 
     } 
     else if scrollView == self.scrollViewB { 
      self.syncScrollView(self.scrollViewA, toScrollView: scrollViewB) 
     } 
    } 

    func syncScrollView(_ scrollViewToScroll: UIScrollView, toScrollView scrolledView: UIScrollView) { 
     var scrollBounds = scrollViewToScroll.bounds 
     scrollBounds.origin.y = scrolledView.contentOffset.y 
     scrollViewToScroll.bounds = scrollBounds 
    } 

Dlatego zamiast ustawiać contentOffset używamy właściwości bounds do zsynchronizowania innego scrollView z tym, który został przewinięty przez użytkownika. W ten sposób metoda delegata nie jest wywoływana cyklicznie, a przewijanie odbywa się bardzo płynnie, z efektami bezwładności i odbijania, jak w przypadku pojedynczego widoku przewijania.

+0

Właśnie wypróbowałem twoje rozwiązanie, ale scrollBounds ma zawsze tę samą wartość. robisz coś innego poza kodem, który podasz? – Jonathanff

+0

Nie. Powiązany z przewijaniem synchronizacji dwóch widoków przewijania, to wszystko, co mam w moim projekcie i działa dobrze. –

Powiązane problemy