2013-02-13 13 views
27

Sto creando un semplice UICollectionView con un meccanismo di paging abilitato e tutto funziona correttamente. Tuttavia, quando scorri fino all'ultima pagina il numero delle celle non è completamente visibile sullo schermo e l'ultima pagina contiene alcune celle della pagina precedente.Come espandere UICollectionView contentSize quando abilita la paginazione?

Come si espande lo contentSize dello UICollectionView in modo che l'ultima pagina non contenga celle della pagina precedente?

Un esempio here: i UICollectionView scorre orizzontalmente con 6 celle, in questo modo:

Pagina 1: cell0 - cell1 - cell2 - cell3

di scorrimento: cell2-CELL3-cell4-cell5 // Non si prevede: come cambiare a: cell4 - cella 5 in pagina2.

SOMMARIO:

voglio impostare

collectionView.contentSize = numberOfPage * collectionView.frame

NON

collectionView.contentSize = numberOfCell * (cellFrame + spacing)

+0

In realtà non dovrebbe accadere. Puoi plz inserire lo snippet di codice, se presente. – Swapnil

+0

Provo: [collectonView setContentSize] in viewDidLoad e viewDidAppear ma non funziona perché contentSize verrà riscritto nell'origine dati. –

risposta

32

È necessario sottoclasse UICollectionViewLayout e sovrascrivere il metodo collectionViewContentSize. Ho creato una sottoclasse di UICollectionViewFlowLayout in modo da non dover riscrivere tutto il codice di layout.

Sto costruendo una griglia di 4x4, quindi il mio metodo è simile al seguente:

- (CGSize)collectionViewContentSize 
{  
    NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; 
    NSInteger pages = ceil(itemCount/16.0); 

    return CGSizeMake(320 * pages, self.collectionView.frame.size.height); 
} 

Nota a margine, quando si utilizza un layout personalizzato, si perde la possibilità di impostare l'alcune delle proprietà di visualizzazione del Interface Builder. È possibile impostarli in modo programmatico nel metodo init della sottoclasse UICollectionViewLayout personalizzata. Ecco il mio per riferimento:

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     [self setup]; 
    } 

    return self; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super init]; 
    if (self) { 
     [self setup]; 
    } 

    return self; 
} 

- (void)setup 
{ 
    self.itemSize = CGSizeMake(65.0f, 65.0f); 
    self.minimumLineSpacing = 15; 
    self.sectionInset = UIEdgeInsetsMake(7.5f, 7.5f, 30.0f, 7.5f); 
    [self setScrollDirection:UICollectionViewScrollDirectionHorizontal]; 
} 
+0

Mi è stato detto che questo genere di cose potrebbe causare un ingombro di memoria enorme perché l'intera vista di raccolta verrebbe "mostrata" e la riusabilità delle celle non sarebbe possibile. È vero? –

+0

UICollectionView è già una sottoclasse di UIScrollView e avere contentSize è naturale per questo, non penso che ci si debba preoccupare della riusolabilità delle celle perché tutte le celle non sono mai visibili. –

+0

'collectionView.collectionViewLayout.collectionViewContentSize()' è quello che ti serve. Se non è valido, solo 'collectionView.layoutIfNeeded()' prima di ottenere contentSize. –

0

È possibile regolare il contenuto con il viewDidLayoutSubviews: m etodo. Questo metodo viene chiamato quando la vista di raccolta e tutte le celle vengono posizionate nello view, in modo da poter regolare la cella.

+0

Non funziona, cellForItemAtIndexPath chiama anche durante lo scorrimento. –

0

Penso che sia necessario creare sottoclasse UICollectionViewLayout e creare il layout personalizzato per gestire questo tipo di problemi.

2

Per paginazione orizzontale

if(CollectionView.pagingEnabled) 
{ 

    int numberOfPages = floor(collectionView.contentSize.width/
         collectionView.frame.size.width) + 1; 
          CGFloat 
    float requierdWidth=self.collectionView.frame.size.width*numberOfPages; 

    self.Layout.footerReferenceSize=CGSizeMake(requierdWidth-self.collectionView.contentSize.width,0); 
} 
1

La risposta funziona bene, anche se per il nostro codice abbiamo avuto una sezione per pagina. Quindi significava che l'override per la nostra classe di layout era solo

-(CGSize) collectionViewContentSize { 
    return CGSizeMake(CGRectGetWidth(self.collectionView.frame) * 
       [self.collectionView numberOfSections], 
       CGRectGetHeight(self.collectionView.frame)) ; 
} 
0

Ho una risposta che non richiede alcuna sottoclasse.

In -viewDidLoad, calcola il numero di elementi per pagina che avrete e il numero di pagine che avrete. Memorizza questi valori nelle proprietà.

self.numberOfItemsPerPage = NumberOfRows * NumberOfColumns; 
    self.numberOfPages = ceilf((CGFloat)self.items.count/(CGFloat)self.numberOfItemsPerPage); 

Poi nel -collectionView: numberOfItemsInSection: semplicemente si trovano ad esso:

return self.numberOfItemsPerPage * self.numberOfPages; 

Naturalmente voi hanno più cellule di contenuti, giusto? Quindi, in -collectionView: cellForItemAtIndexPath: basta restituire nil per le cellule extra:

if (indexPath.item > [self.items count] - 1) { 
    //We have no more items, so return nil. This is to trick it to display actual full pages. 
    return nil; 
    } 

ci si va: pieno, scorrevole pagina finale. A mio parere, la modalità di scorrimento orizzontale dovrebbe essere impostata solo su questo.

+0

Piuttosto sicuro che una cella non può essere nil :(Ho provato questo e ho ottenuto questo errore: '*** Terminare l'app a causa dell'eccezione non rilevata 'NSInternalInconsistencyException', motivo: 'l'origine dati della vista dell'insieme non ha restituito una cella valida da -collectionView: cellForItemAtIndexPath: per il percorso dell'indice ' – taber

Problemi correlati