2012-11-01 18 views
36

Podczas nauki iOS6 nowych funkcji dostałem pytanie o UICollectionView.
Obecnie testuję to z układem przepływu, a kierunek przewijania jest ustawiony na poziomy, przewijanie i obsługa stronicowania włączona. Ustawiłem jego rozmiar dokładnie tak samo, jak komórki mojego klienta, aby mógł wyświetlać jeden na raz, a po przewinięciu na bok użytkownik zobaczyłby pozostałe istniejące komórki.iOS6 UICollectionView i UIPageControl - jak uzyskać widoczne komórki?

Działa doskonale.

Teraz chcę dodać i UIPageControl do utworzonego przeze mnie widoku kolekcji, aby mógł pokazać, która komórka jest widoczna i ile jest tam komórek.

Tworzenie kontroli strony było raczej proste, zdefiniowano ramkę i numberOfPages.

Problem, który mam jako znaczniki tytułów pytań, polega na określeniu, która komórka jest obecnie widoczna w widoku kolekcji, aby można było zmienić bieżącą stronę kontrolki strony.

Próbowałem już metod delegatów, takich jak cellForItemAtIndexPath, ale jest on przeznaczony do ładowania komórek, a nie ich wyświetlania. didEndDisplayingCell uruchamia się, gdy komórka nie jest już wyświetlana, przeciwnie do tego, czego potrzebuję.

Jego wydaje się, że -visibleCells i -indexPathsForVisibleItems, metody widoku kolekcji, są właściwym wyborem dla mnie, ale wpadł na inny problem. Kiedy je wyzwolić?

Z góry dziękuję, mam nadzieję, że zrobiłem się wystarczająco jasny, abyście mogli mnie zrozumieć!

Odpowiedz

91

musisz ustawić siebie jako UIScrollViewDelegate i wdrożenie metody scrollViewDidEndDecelerating: tak:

Objective-C

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    CGFloat pageWidth = self.collectionView.frame.size.width; 
    self.pageControl.currentPage = self.collectionView.contentOffset.x/pageWidth; 
} 

Swift

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 

    let pageWidth = self.collectionView.frame.size.width 
    pageControl.currentPage = Int(self.collectionView.contentOffset.x/pageWidth) 
} 
+2

bez konieczności tworzenia ivar dla CollectionView: '- (void) scrollViewDidEndDecelerating (UIScrollView *) Scrollview { CGFloat pageWidth = _tutorialCollectionViewFrame.size.width; _pageControl.currentPage = scrollView.contentOffset.x/pageWidth; } ' – mmackh

+1

+10 jeśli mogę: D – Omarj

+1

Tak to jest prawidłowa odpowiedź ...: func scrollViewDidEndDecelerating (Scrollview: UIScrollView) { niech pageWidth: CGFloat = self.collectionView.frame.size.width self.pageControl.currentPage = Int (self.collectionView.contentOffset.x/pageWidth) } –

18

Zmagałem się z tym przez chwilę, a następnie polecono mi sprawdzenie klas nadrzędnych UICollectionView. Jednym z nich jest UIScrollView, a jeśli ustawisz się jako UIScrollViewDelegate, uzyskasz dostęp do bardzo pomocnych metod, takich jak scrollViewDidEndDecelerating, świetne miejsce do aktualizacji UIPageControl.

+0

Dzięki wielkie! Rozwiązałem mój problem. – gazzola

+0

Dodałem do mojego UIViewController delegata, ale nadal metoda nie jest wywoływana. Dowolny pomysł? – Dejell

+0

@Dejel Pamiętaj, aby ustawić delegata przewijania. – user1898829

16

Polecam trochę dostrojony obliczenia i obsługa, jak to się podniesie Ta strona kontroluje natychmiast w dowolnym położeniu przewijania z większą dokładnością.

poniżej Rozwiązanie współpracuje z dowolnym widoku przewijania albo podklasy (UITableView UICollectionView i inne)

w metodzie viewDidLoad napisać to

scrollView.delegate = self 

następnie użyć kodu na swoim języku:

Swift 3

func scrollViewDidScroll(_ scrollView: UIScrollView) 
    { 
     let pageWidth = scrollView.frame.width 
     pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth/2)/pageWidth) 
    } 

Swift 2:

func scrollViewDidScroll(scrollView: UIScrollView) 
{ 
    let pageWidth = CGRectGetWidth(scrollView.frame) 
    pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth/2)/pageWidth) 
} 

Objective C

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    CGFloat pageWidth = self.collectionView.frame.size.width; 
    self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth/2)/pageWidth; 
} 
+0

Twoje obliczenia są lepsze, ale '- [scrollViewDidEndDecelerating:]' jest lepszym miejscem dla tego kodu. – k06a

+0

To zależy od Twojego gustu, myślę. Apple aktualizuje pageControl po zakończeniu przewijania, ale dla mnie aktualizacja kontroli strony częściej wygląda lepiej dla użytkownika. Jeśli nie spowalnia to działania, możesz skorzystać z tej metody. –

+0

Widziałem nie fajne miganie podczas stukania w lewą i prawą część 'UIPageControl' w tym przypadku. Mam na myśli zmianę strony przez dotykanie 'UIPageControl'. – k06a

5
  1. Place PageControl w widoku lub ustawić poprzez kod.
  2. Ustaw UIScrollViewDelegate
  3. W CollectionView -> cellForItemAtIndexPath (metoda) dodać poniższy kod do obliczenia liczby stron,

stron int = floor (ImageCollectionView.contentSize. width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages: pages];

Dodaj Scrollview Delegowanie metody

pragma mark - UIScrollVewDelegate dla UIPageControl

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    CGFloat pageWidth = ImageCollectionView.frame.size.width; 
    float currentPage = ImageCollectionView.contentOffset.x/pageWidth; 

    if (0.0f != fmodf(currentPage, 1.0f)) 
    { 
     pageControl.currentPage = currentPage + 1; 
    } 
    else 
    { 
     pageControl.currentPage = currentPage; 
    } 
    NSLog(@"finishPage: %ld", (long)pageControl.currentPage); 
} 
8

Inną opcją mniej kodu jest użycie widoczną ścieżkę indeks towaru i ustawić regulator strony.

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row]; 
} 
+0

To byłoby najprostsze i działało – anoop4real

3

Proste Swift

public func scrollViewDidEndDecelerating(scrollView: UIScrollView) { 
    pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)! 
} 

UIScrollViewDelegate jest już realizowane, jeśli wdrożyć UICollectionViewDelegate

+0

Zauważyłem, że zaakceptowana odpowiedź działa lepiej, ponieważ zajmuje wiersz w środku widoku przewijania. – markhorrocks

4

wiem, że to jest stary, ale ja po prostu potrzebne do wdrożenia tego rodzaju funkcję ponownie i trochę dodać, co daje bardziej kompletną odpowiedź.

pierwsze: Stosując scrollViewDidEndDecelerating zakłada, że ​​użytkownik podniósł palcem podczas przeciągania (raczej działanie flick), a zatem nie jest w fazie zwalniania. Jeśli użytkownik przeciągnie bez podnoszenia palca, to nadal będzie wskazywał starą stronę przed rozpoczęciem przeciągania. Zamiast tego korzystanie z funkcji oddzwaniania scrollViewDidScroll oznacza, że ​​widok jest aktualizowany zarówno po przeciągnięciu, jak i przeciągnięciu, a także podczas przeciągania i przewijania, dzięki czemu jest bardziej responsywny i dokładny dla użytkownika.

Po drugie: Poleganie na pagewidth w celu obliczenia wybranego indeksu zakłada, że ​​wszystkie komórki mają tę samą szerokość i że istnieje jedna komórka na ekranie. skorzystanie z metody indexPathForItemAtPoint na UICollectionView daje bardziej elastyczny wynik, który zadziała dla różnych układów i rozmiarów komórek. Poniższa implementacja zakłada, że ​​środek ramki jest pożądaną komórką, która ma być reprezentowana w pagecontrol. Również jeśli istnieją odstępy między komórkami, będą występować czasy podczas przewijania, gdy selectedIndex może być zerowy lub opcjonalny, więc należy to sprawdzić i rozpakować przed ustawieniem na stronieControl.

func scrollViewDidScroll(scrollView: UIScrollView) { 
    let contentOffset = scrollView.contentOffset 
    let centrePoint = CGPointMake(
    contentOffset.x + CGRectGetMidX(scrollView.frame), 
    contentOffset.y + CGRectGetMidY(scrollView.frame) 
    ) 
    if let index = self.collectionView.indexPathForItemAtPoint(centrePoint){ 
    self.pageControl.currentPage = index.row 
    } 
} 

jeszcze jedno - ustawić liczbę stron na UIPageControl z mniej więcej tak:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    self.pageControl.numberOfPages = 20 
    return self.pageControl.numberOfPages 
    } 
Powiązane problemy