Die aktuelle Seite abrufen

97

In meiner Bildlaufansicht möchte ich die aktuelle Seite abrufen, die angezeigt wird (möglicherweise ist die Seite nicht der richtige Begriff). Ich kann keine Variable finden, die dies enthält. Aber ich denke, es muss irgendwo gehalten werden, da der Indikator anzeigen kann, welche Unteransicht der Bildlaufansicht gerade angezeigt wird.

Ist das uns völlig verborgen oder gibt es eine Möglichkeit für mich, darauf zuzugreifen?

TheNeil
quelle

Antworten:

263

Es gibt keine UIScrollViewEigenschaft für die aktuelle Seite. Sie können es berechnen mit:

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

Wenn Sie auf die nächste Seite auf- oder abrunden möchten, verwenden Sie:

CGFloat width = scrollView.frame.size.width;
NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;
AlexVogel
quelle
7
Vergessen Sie nicht, die zu verwenden UIScrollViewDelegate, um die aktuelle Seite zu erhalten, wenn der Benutzer einen Bildlauf durchführt!
Sam Spencer
Dies kann Probleme beim Umgang mit Rotation haben.
Jason McCreary
Bitte fügen Sie schnelle Version
FNC12
1
Dies funktioniert nicht immer, manchmal ist die Rahmenbreite falsch.
Rodrigo Ruiz
Das funktioniert nicht immer. Manchmal bekomme ich die Seite als 0, was in meinem Fall falsch ist.
Sneha
32

Ich empfehle Ihnen ziemlich, diesen Code zu verwenden

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

Wenn Sie diesen Code verwenden, muss sich Ihre Ansicht nicht genau auf der Seite befinden, die indexOfPage Ihnen bietet. Dies liegt daran, dass ich Ihnen auch empfehle, diesen Code nur in dieser Methode zu verwenden

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

Dies wird aufgerufen, wenn Ihre scrollView mit dem Scrollen fertig ist und die Nummer Ihrer Seite wirklich scharf ist

Ich empfehle Ihnen, Ihre scrollView so einzustellen, dass sie mit diesem Code aktiviert ist

[scrollView setPagingEnabled:YES];

Also sollte es endlich so aussehen

-(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
}
Jiří Zahálka
quelle
funktioniert nicht auf iOS7-Geräten (kompiliert mit XCODE 6.2) contentOffset.x entspricht 639 statt 640 (frag mich nicht warum ...), wenn scrollViewDidEndDecelerating. Die Antwort von user363349 ist korrekt: return floor ((self.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
Vassily
Das funktioniert nicht immer. Manchmal bekomme ich die Seite als 0, was in meinem Fall falsch ist.
Sneha
30

In Kürze würde ich es in Erweiterung tun:

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

Dann rufen Sie einfach an:

scrollView.currentPage
Andrius Steponavičius
quelle
10
Fast perfekt, ich musste die +1 am Ende entfernen, da in meiner Welt alles auf Null steht
mvandillen
12

Wie oben, aber als Kategorie


@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
user363349
quelle
6
Das ist übertrieben, verwenden Sie einfach return round (self.contentOffset.x / self.frame.size.width); Viel einfacher und leichter zu verstehen ..
Leonard Pauli
-1 @LeonardPauli. Die obige Implementierung gibt die Seite zurück, die zu mehr als 50% sichtbar ist. Die naive Implementierung ändert den Seitenwert nur, wenn die Unteransicht der Bildlaufansicht die gesamten Grenzen der Bildlaufansicht einnimmt.
Benutzer
1
@user Erstens rundet floor () immer ab und round () rundet auf, wenn der Dezimalteil> = 5 ist, sonst down. Damit ist Boden (a) = rund (a-0,5). Lassen Sie uns eine einfache Algebra machen. Boden ((ab / 2) / b) +1 = Boden (a / b-0,5) +1 = rund (a / b-0,5-0,5) +1 = rund (a / b-1) +1 = rund ( a / b). Aussehen! Es scheint wie Boden ((ab / 2) / b) +1 = rund (a / b)! Mathematisch.
Leonard Pauli
Aber ja, wenn ich aus irgendeinem Grund stattdessen Boden verwendet hätte, dann hätten Sie vollkommen recht gehabt! ;)
Leonard Pauli
8

Ein anderer Weg :

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

Teilen Sie einfach den aktuellen Versatz durch die Seitengröße:

CGFloat pageNum = (int)(scrollView.contentOffset.x / scrollView.frame.size.width);
aoakenfo
quelle
11
Casting auf int und dann Zuordnung zu einem Float? Warum nicht auch pageNum int machen;)
Klaas
6

Hier gibt es bereits einige gute Antworten. Für Szenarien, in denen der Inhalt nicht genau in eine Seite passt - und wenn Sie wie ich das Ergebnis für a verwenden möchten UIPageControl, ist es wichtig, das zu verwendenceil Funktion zu verwenden.

Nehmen wir ein Beispiel, in dem ich "vier und ein bisschen" Inhaltsseiten habe.

Ich werde dies auf mein aktuelles Beispiel aus dem wirklichen Leben stützen. Die Breite der Inhaltsgröße beträgt 3140 Punkte. Basierend auf der Rahmengröße meiner Sammlungsansicht beträgt die Seitenbreite 728.

Die Anzahl der Seiten entspricht also:

 3140 / 728 = 4.313 

Mein numberOfPageswird fünf sein. Vier davon werden vollständig angezeigt, und der letzte - Seite fünf - zeigt den verbleibenden Wert0.313 Inhalt.

Jetzt, numberOfPages fünf Mittel ist , dass die Seite Indizes 0, 1, 2, 3 und 4 sein.

Wenn ich nach rechts wische und in Richtung des endgültigen Versatzes blättere, wird der scrollViewDidEndDecelerating ergibt Methode einen endgültigen X-Versatz von 2412.

Anwenden der Rundungsberechnung:

2412 / 728 = 3.313 then rounded = 3

Das ist falsch Der Seitenbenutzer, der nach Versatz angezeigt wird, sollte sein:

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

Die korrekte Berechnung mit 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
}
Max MacLeod
quelle
4

Für schnell würde ich nur diese verwenden

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

Ziemlich einfach, nimmt es im Grunde die Position x der Bildlaufansicht ein, dividiert sie durch die Breite der Bildlaufansicht und rundet sie dann ab.

Neptune
quelle
3

In xCode 7.x swift 2.x können Sie Folgendes tun:

//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
    }
}
Alessandro Ornano
quelle
3

Die Lösung von Aoakenfo ist erstaunlich. Dies ist eine weitere Lösung, die Ihren Code mit der Funktion scrollViewDidScroll und PageController kombiniert

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    if (sender == self.scroll) {
        int pageNum = (int)(self.scrPage.contentOffset.x / self.scrPage.frame.size.width);
        self.pagecontroller.currentPage =pageNum;
    }
}
pabloverd
quelle
1
Das ist gierig, nicht faul ... Es ist auch nicht MVC. Eine viel einfachere Möglichkeit besteht darin, die aktuelle Seite beim Scrollen ungültig zu machen und sie nur festzulegen, wenn sie angefordert wird ... alles aus einer Unterklasse oder Kategorie in UIScrollView
2

Ich habe dies aus einigen unserer Apps extrahiert ...

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

Vollständige Quelle hier


quelle
1

Verwenden Sie ein UIPageControl? Wenn ja, hat dies eine currentPageEigenschaft. Wenn nicht, müssen Sie den Seitenindex aus dem scrollView-Offset berechnen.

Rengers
quelle
0

Wenn jemand nach einer Möglichkeit sucht, in C # für Xamarin vorzugehen

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

Dieser Getter und Setter sollten Ihnen auch die aktuelle Seite zur Verfügung stellen, damit Sie zur angegebenen Seite scrollen können

Soan Saini
quelle
0

Swift 5.1+ UIScrollView-Erweiterung (ohne das Schlüsselwort return)

extension UIScrollView {

    var currentPage: Int {
        Int(round(self.contentOffset.x / self.frame.width))
    }
}
Diego Carrera
quelle