Pull-to-Refresh in UICollectionViewController

72

Ich möchte Pulldown-to-Refresh UICollectionViewControllerunter iOS 6 implementieren . Dies war mit einem UITableViewControllerwie folgt einfach zu erreichen :

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(startRefresh:)
    forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;

Das obige implementiert eine nette Liquid-Drop-Animation als Teil eines nativen Widgets.

Da UICollectionViewControlleres sich um eine "weiterentwickelte" UITableViewControllerVersion handelt, würde man eine gewisse Parität von Funktionen erwarten, aber ich kann nirgendwo einen Hinweis auf eine integrierte Methode finden, um dies zu implementieren.

  1. Gibt es eine einfache Möglichkeit, dies zu tun, die ich übersehen habe?
  2. Kann trotz des Headers und der Dokumente, die beide angeben, dass es für die Verwendung mit einer Tabellenansicht vorgesehen UIRefreshControlist, irgendwie UICollectionViewControllerverwendet werden?
mjh
quelle

Antworten:

215

Die Antworten auf (1) und (2) lauten ja.

UIRefreshControlFügen .collectionViewSie einfach eine Instanz als Unteransicht von hinzu und es funktioniert einfach.

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(startRefresh:)
    forControlEvents:UIControlEventValueChanged];
[self.collectionView addSubview:refreshControl];

Das ist es! Ich wünschte, dies wäre irgendwo in der Dokumentation erwähnt worden, obwohl manchmal ein einfaches Experiment den Trick macht.

BEARBEITEN: Diese Lösung funktioniert nicht, wenn die Sammlung nicht groß genug ist, um eine aktive Bildlaufleiste zu haben. Wenn Sie diese Anweisung hinzufügen,

self.collectionView.alwaysBounceVertical = YES;

dann funktioniert alles perfekt. Dieser Fix stammt aus einem anderen Beitrag zum gleichen Thema (auf den in einem Kommentar in der anderen geposteten Antwort verwiesen wird).

mjh
quelle
51
Ich muss darauf hinweisen, dass UIRefreshControl.alloc.init ein Missbrauch der Punktnotation ist. Die Punktnotation soll den Zugriff auf den internen Status vermitteln, während die Klammernotation vermitteln soll, dass ein Objekt eine Aktion ausführen soll.
Peter Willsey
1
Stellen Sie sich das wie ein verzögertes Laden vor, bei dem der interne Status, auf den zugegriffen wird, eine initialisierte Instanz ist. Eine Strecke, aber das ist besser als meine anfängliche Antwort, die nur ": p" sein sollte. :)
mjh
Wenn Sie hier die Punktnotation verwenden möchten, bevorzuge ich UIRefreshControl.new
JLundell
2
@ JuanGonzález: Stellen Sie das Steuerelement auf einen iVar, ala _refreshControl = blah, und führen Sie dann startRefresh:, wenn die Arbeit erledigt ist, a aus _refreshControl endRefreshing];.
Josh
1
Wenn jemand interessiert ist und Swift verwendet, habe ich eine schnelle, einfache Erweiterung für UICollectionViewController geschrieben, um eine praktische Variable für refreshControl zu erhalten. gist.github.com/Baza207/f5ff5abf7b8c44e2ffb3
Baza207
18

Ich suchte nach der gleichen Lösung, aber in Swift. Basierend auf der obigen Antwort habe ich Folgendes getan:

let refreshCtrl = UIRefreshControl()
    ...
refreshCtrl.addTarget(self, action: "startRefresh", forControlEvents: .ValueChanged)
collectionView?.addSubview(refreshCtrl)

Nicht zu vergessen:

refreshCtrl.endRefreshing()
djbp
quelle
7

Ich habe Storyboard verwendet und die Einstellung self.collectionView.alwaysBounceVertical = YES;hat nicht funktioniert. Auswahl der Bouncesund Bounces Verticallyerledigt den Job für mich.

Geben Sie hier die Bildbeschreibung ein

Harinsa
quelle
4

Die refreshControlEigenschaft wurde ab UIScrollViewiOS 10 hinzugefügt, sodass Sie das Aktualisierungssteuerelement direkt in Sammlungsansichten festlegen können.

https://developer.apple.com/reference/uikit/uiscrollview/2127691-refreshcontrol

UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:@selector(refreshControlAction:) forControlEvents:UIControlEventValueChanged];
self.collectionView.refreshControl = refreshControl;    
Beerenblau
quelle
2

Die Antwort von mjh ist richtig.

Ich bin auf das Problem gestoßen, dass man, wenn das collectionView.contentSizenicht größer als das ist collectionView.frame.size, das Scrollen nicht bekommen kann collectionView. Sie können die contentSizeEigenschaft auch nicht festlegen (zumindest konnte ich nicht).

Wenn es nicht scrollen kann, können Sie nicht zum Aktualisieren ziehen.

Meine Lösung bestand UICollectionViewFlowLayoutdarin, die Methode zu unterordnen und zu überschreiben:

- (CGSize)collectionViewContentSize
{
    CGFloat height = [super collectionViewContentSize].height;

    // Always returns a contentSize larger then frame so it can scroll and UIRefreshControl will work
    if (height < self.collectionView.bounds.size.height) {
        height = self.collectionView.bounds.size.height + 1;
    }

    return CGSizeMake([super collectionViewContentSize].width, height);
}
Padin215
quelle
13
Sie können auch tun self.collectionView.alwaysBounceVertical = YES;. Gutschrift geht an diese Antwort .
BFar