web-dev-qa-db-fra.com

Pull-to-refresh dans UICollectionViewController

Je veux implémenter le pull-down-to-refresh dans un UICollectionViewController sous iOS 6. Cela a été facile à réaliser avec un UITableViewController, comme ceci:

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

Ce qui précède implémente une belle animation de goutte de liquide dans le cadre d'un widget natif.

Étant donné que UICollectionViewController est une version "plus évoluée" UITableViewController, on peut s'attendre à une certaine parité de fonctionnalités, mais je ne trouve nulle part une référence à un moyen intégré de mettre en œuvre cela.

  1. Existe-t-il un moyen simple de faire cela que je néglige?
  2. UIRefreshControl peut-il être utilisé d'une manière ou d'une autre avec UICollectionViewController malgré l'en-tête et les documents indiquant tous deux qu'il est destiné à être utilisé avec une vue de table?
73
mjh

Les réponses aux questions (1) et (2) sont oui.

Ajoutez simplement une instance UIRefreshControl en tant que sous-vue de .collectionView et ça marche.

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

C'est ça! Je souhaite que cela ait été mentionné quelque part dans la documentation, même si parfois une simple expérience fait l'affaire.

EDIT: cette solution ne fonctionnera pas si la collection n'est pas assez grande pour avoir une barre de défilement active. Si vous ajoutez cette déclaration,

self.collectionView.alwaysBounceVertical = YES;

alors tout fonctionne parfaitement. Ce correctif provient de n autre message sur le même sujet (référencé dans un commentaire dans l'autre réponse publiée).

215
mjh

Je cherchais la même solution, mais chez Swift. Sur la base de la réponse ci-dessus, j'ai fait ce qui suit:

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

Sans oublier de:

refreshCtrl.endRefreshing()
18
djbp

J'utilisais Storyboard et définissais self.collectionView.alwaysBounceVertical = YES; n'a pas fonctionné. Sélection de Bounces et Bounces Vertically fait le travail pour moi.

enter image description here

7
harinsa

La propriété refreshControl a maintenant été ajoutée à UIScrollView à partir d'iOS 10 afin que vous puissiez définir le contrôle d'actualisation directement sur les vues de collection.

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;    
4
Berry Blue

la réponse de mjh est correcte.

Je suis tombé sur le problème où si le collectionView.contentSize n'était pas plus grand que le collectionView.frame.size, vous ne pouvez pas faire défiler le collectionView. Vous ne pouvez pas non plus définir la propriété contentSize (du moins je ne pouvais pas).

S'il ne peut pas défiler, il ne vous laissera pas tirer pour vous rafraîchir.

Ma solution a été de sous-classer UICollectionViewFlowLayout et de remplacer la méthode:

- (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);
}
2
Padin215