Pobieranie bieżącej strony


97

W moim widoku przewijania chcę uzyskać bieżącą wyświetlaną stronę (może strona nie jest właściwym terminem). Nie mogę znaleźć żadnej zmiennej, która to przechowuje. Ale myślę, że trzeba to gdzieś trzymać, ponieważ wskaźnik jest w stanie pokazać, który podwidok widoku przewijania jest obecnie wyświetlany.

Czy jest to całkowicie przed nami ukryte, czy jest dla mnie sposób, aby uzyskać do niego dostęp?

Odpowiedzi:


263

Nie ma UIScrollViewwłaściwości dla bieżącej strony. Możesz to obliczyć za pomocą:

int page = scrollView.contentOffset.x / scrollView.frame.size.width;

Jeśli chcesz zaokrąglić w górę lub w dół do najbliższej strony, użyj:

CGFloat width = scrollView.frame.size.width;
NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;

7
Nie zapomnij użyć, UIScrollViewDelegateaby uzyskać bieżącą stronę, gdy użytkownik przewija!
Sam Spencer

Może to powodować problemy w przypadku rotacji.
Jason McCreary

proszę dodać szybką wersję
fnc12

1
To nie zawsze działa, czasami szerokość ramy jest nieprawidłowa.
Rodrigo Ruiz

To nie zawsze działa. Czasami otrzymuję stronę jako 0, co jest błędne w moim przypadku.
Sneha

32

Całkiem polecam użycie tego kodu

int indexOfPage = scrollView.contentOffset.x / scrollView.frame.size.width;

ale jeśli użyjesz tego kodu, twój widok nie musi znajdować się dokładnie na stronie, którą daje indexOfPage. To dlatego, że również polecam używać tego kodu tylko w tej metodzie

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{}

która jest wywoływana, gdy scrollView kończy przewijanie i ma naprawdę ostry numer strony

Zalecam ustawienie scrollView na stronicowane włączone za pomocą tego kodu

[scrollView setPagingEnabled:YES];

Więc w końcu powinno tak wyglądać

-(void) methodWhereYouSetYourScrollView
{
   //set scrollView
   [scrollView setPagingEnabled:YES];
   scrollView.delegate = self;
}

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
   int indexOfPage = scrollView.contentOffset.x / scrollView.frame.size.width;
   //your stuff with index
}

nie działa na urządzeniu iOS7 (skompilowanym z XCODE 6.2) contentOffset.x równa się 639 zamiast 640 (nie pytaj mnie dlaczego ...) podczas scrollViewDidEndDecelerating. user363349 odpowiedź jest prawidłowa: return floor ((self.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
Wasilij

To nie zawsze działa. Czasami otrzymuję stronę jako 0, co jest błędne w moim przypadku.
Sneha

30

Szybko zrobiłbym to w rozszerzeniu:

extension UIScrollView {
    var currentPage:Int{
        return Int((self.contentOffset.x+(0.5*self.frame.size.width))/self.frame.width)+1
    }
}

Następnie zadzwoń:

scrollView.currentPage

10
Prawie idealnie, musiałem usunąć +1 na końcu, ponieważ w moim świecie wszystko jest zerowe
mvandillen

12

Jak wyżej, ale jako kategoria


@interface UIScrollView (CurrentPage)
-(int) currentPage;
@end
@implementation UIScrollView (CurrentPage)
-(int) currentPage{
    CGFloat pageWidth = self.frame.size.width;
    return floor((self.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
}
@end

6
To przesadzone, po prostu użyj return round (self.contentOffset.x / self.frame.size.width); Dużo prostsze i łatwiejsze do zrozumienia ..
Leonard Pauli

-1 @LeonardPauli. Powyższa implementacja zwraca stronę, która jest widoczna w ponad 50%. Naiwna implementacja zmienia wartość strony tylko wtedy, gdy widok podrzędny widoku przewijania zajmuje całe granice widoku przewijania.
użytkownik

1
@user Po pierwsze, floor () zaokrągla zawsze w dół, a round () zaokrągla w górę, jeśli część dziesiętna wynosi> = 5, w przeciwnym razie w dół. Mając to na uwadze, floor (a) = round (a-0.5). Zróbmy prostą algebrę. podłoga ((ab / 2) / b) +1 = podłoga (a / b-0,5) +1 = okrągła (a / b-0,5-0,5) +1 = okrągła (a / b-1) +1 = okrągła ( a / b). Popatrz! Wygląda na to, że podłoga ((ab / 2) / b) +1 = okrągły (a / b)! Matemagiczne.
Leonard Pauli

Ale tak, gdybym z jakiegoś powodu użył zamiast tego podłogi, miałbyś całkowitą rację! ;)
Leonard Pauli

8

Inny sposób :

extension MyViewController: UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let width = scrollView.frame.width
        let page = Int(round(scrollView.contentOffset.x/width))
        print("CurrentPage:\(page)")
    }
}

6

Po prostu podziel bieżące przesunięcie przez rozmiar strony:

CGFloat pageNum = (int)(scrollView.contentOffset.x / scrollView.frame.size.width);

11
Rzutowanie na int, a następnie przypisanie do pływaka? Dlaczego nie zrobić również pageNum int;)
Klaas

6

Jest tu już kilka dobrych odpowiedzi. Jednak w scenariuszach, w których treść nie pasuje dokładnie do strony - i jeśli tak jak ja chcesz użyć wyniku dla a UIPageControl, to konieczne jest użycie ceilfunkcji.

Weźmy przykład, w którym mam „cztery i trochę” strony treści.

Oprę to na moim obecnym przykładzie z życia. Szerokość rozmiaru treści to 3140 punktów. Na podstawie rozmiaru ramki widoku mojej kolekcji szerokość strony to 728.

Tak więc liczba stron jest równa:

 3140 / 728 = 4.313 

Mój numberOfPagesbędzie miał pięć lat. Cztery z nich wyświetlą się w całości, a ostatnia - strona piąta - pokaże pozostałą 0.313treść.

Teraz, numberOfPagesgdy jest pięć, oznacza, że ​​indeksy stron będą wynosić 0, 1, 2, 3 i 4.

Kiedy przesuwam palcem w prawo, przewijając w kierunku końcowego przesunięcia, scrollViewDidEndDeceleratingmetoda daje końcowe przesunięcie X o wartości 2412.

Stosowanie obliczenia zaokrąglenia:

2412 / 728 = 3.313 then rounded = 3

To jest niepoprawne. Strona przeglądana przez użytkownika według przesunięcia powinna być:

Offset / Page User Is Viewing
0        0
728      1
1456     2
2184     3
2412     4

Prawidłowe obliczenia przy użyciu ceil:

private func pageForOffset(offset:CGFloat, pageWidth width:CGFloat) -> Int
{
    let page = Int(ceil(offset / width))
    NSLog("\(__FUNCTION__) offset \(offset) width \(width) page \(page) ")
    return page
}

4

Szybko użyłbym tego

    let width = scrollView.frame.width
    let page = round(scrollView.contentOffset.x/width)

Całkiem proste, w zasadzie przyjmuje pozycję scrollview x, dzieli ją przez szerokość scrollview, a następnie zaokrągla.


3

W xCode 7.x swift 2.x możesz:

//MARK: - ScrollView Extensions
// Get the current page number
extension UIScrollView {
    var currentPage: Int {
        return Int(round(self.contentOffset.x / self.bounds.size.width))
    }

// If you have reversed offset (start from contentSize.width to 0)
    var reverseCurrentPage: Int {
        return Int(round((contentSize.width - self.contentOffset.x) / self.bounds.size.width))-1
    }
}

3

Rozwiązanie Aoakenfo jest niesamowite, to kolejne rozwiązanie łączące Twój kod z funkcją scrollViewDidScroll i PageController

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    if (sender == self.scroll) {
        int pageNum = (int)(self.scrPage.contentOffset.x / self.scrPage.frame.size.width);
        self.pagecontroller.currentPage =pageNum;
    }
}

1
To jest chciwe, nie leniwe ... To też nie jest MVC. O wiele prostszym sposobem jest unieważnienie bieżącej strony podczas przewijania i ustawianie jej tylko wtedy, gdy jest żądana ... wszystko z podklasy lub kategorii w UIScrollView

2

Wyodrębniłem to z kilku naszych aplikacji ...

- (NSInteger)currentPage
{
    if (0 == self.frame.size.width) {
        NSLog(@"frame width == 0!");
        return 0;
    }
    if (! self.currentPageValid) {
        _currentPage = round(self.contentOffset.x / self.frame.size.width);
        self.currentPageValid = YES;
    }
    return _currentPage;
}

Pełne źródło tutaj


1

Czy używasz UIPageControl? Jeśli tak, to ma currentPagewłaściwość. Jeśli nie, myślę, że będziesz musiał obliczyć indeks strony na podstawie przesunięcia scrollView.


0

Jeśli ktoś szuka sposobu działania w języku C # dla platformy Xamarin

    public int CurrentIndex
    {
        get => (int)Math.Round(this.scrollView.ContentOffset.X / this.scrollView.Frame.Width);
        set => this.scrollView.ScrollRectToVisible(new CGRect(new CGPoint(this.scrollView.Frame.Size.Width * value, 0), this.scrollView.Frame.Size), true);
    }

Ten program pobierający i ustawiający powinien również zapewnić bieżącą stronę, umożliwiającą przewijanie do określonej strony


0

Rozszerzenie Swift 5.1+ UIScrollView (pomijanie słowa kluczowego return)

extension UIScrollView {

    var currentPage: Int {
        Int(round(self.contentOffset.x / self.frame.width))
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.