2013-01-23 4 views
9

Sto utilizzando UICollectionView per presentare una griglia di immagini in un'app per iPhone (iOS6).Visualizzare le immagini in un UICollectionView - come ottenere una spaziatura verticale fissa tra le immagini?

Sto usando lo scorrimento verticale per l'UICollectionView, e le immagini tutti hanno fissato la larghezza e l'altezza variabile. La larghezza delle immagini è impostata in modo che su un iPhone, visualizza 3 colonne di immagini. Funziona bene e ottengo le immagini presentate in una griglia.

Tuttavia, dato che le mie immagini sono altezza variabile, la spaziatura verticale tra le immagini in una colonna varia e questo non sembra molto buona, come si può vedere nell'immagine seguente (un mockup realizzato in HTML):

Image showing how the images are currently laid out

Vorrei invece ottenere un flusso più fluido, in cui la spaziatura verticale tra le immagini in una colonna è la stessa. Il seguente mockup mostra come vorrei farlo funzionare:

Example of how I would like the flow of images to work

Tutte le idee su come risolvere questo problema?

Inoltre, come domanda bonus, qualcuno sa come risolvere lo stesso problema se l'app non è stata creata per iOS6 (poiché UICollectionView è disponibile solo in iOS6). O utilizzando un componente di terze parti o risolvendolo con i controlli iOS standard.

risposta

8

Sottoclasse UICollectionViewFlowLayout e in questa classe aggiungere questi metodi. (Nota: questo presuppone un orientamento verticale, e salta la prima linea, ed è una costante di 10 pixel tra di loro Vedi:. how do you determine spacing between cells in UICollectionView flowLayout se avete bisogno della versione orizzontale

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 
NSArray* arr = [super layoutAttributesForElementsInRect:rect]; 
for (UICollectionViewLayoutAttributes* atts in arr) { 
    if (nil == atts.representedElementKind) { 
     NSIndexPath* ip = atts.indexPath; 
     atts.frame = [self layoutAttributesForItemAtIndexPath:ip].frame; 
    } 
} 
return arr; 
} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { 
UICollectionViewLayoutAttributes* atts = 
[super layoutAttributesForItemAtIndexPath:indexPath]; 

if (indexPath.item == 0 || indexPath.item == 1) // degenerate case 1, first item of section 
    return atts; 

NSIndexPath* ipPrev = 
[NSIndexPath indexPathForItem:indexPath.item-2 inSection:indexPath.section]; 

CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame; 
CGFloat rightPrev = fPrev.origin.y + fPrev.size.height + 10; 
if (atts.frame.origin.y <= rightPrev) // degenerate case 2, first item of line 
    return atts; 

CGRect f = atts.frame; 
f.origin.y = rightPrev; 
atts.frame = f; 
return atts; 
} 
+1

Grazie per l'aiuto con questo per altri che cercano a questo, le soluzioni risposta opere alla fine ho finito per usare un componente di terze parti, invece, https: //github.com/ptshih/PSCollectionView. Ciò mi ha permesso di scegliere come target anche iOS5. – Jonas

+1

Ho capito come fornire la spaziatura, ma come posso impostare la dimensione della singola cella sopra codice? – Satyam

+2

@Satyamsvv Utilizzare il metodo delegato per UICollectionViewFlowLayout nella classe ViewController (non il layout sottoclasse) - (CGSize) CollectionView: (UICollectionView *) CollectionView disposizione: (UICollectionViewLayout *) collectionViewLayout sizeForItemAtIndexPath: (NSIndexPath *) indexPath – nsuinteger

3

Per Swift 3 questo lavoro di codice per me, !. incluso lo spazio di prima linea in alto ...

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
    let arr = super.layoutAttributesForElements(in: rect) 

    for atts:UICollectionViewLayoutAttributes in arr! { 
     if nil == atts.representedElementKind { 
      let ip = atts.indexPath 
      atts.frame = (self.layoutAttributesForItem(at: ip)?.frame)! 
     } 
    } 
    return arr 
} 

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 
    let atts = super.layoutAttributesForItem(at: indexPath) 

    if indexPath.item == 0 || indexPath.item == 1 { 
     var frame = atts?.frame; 
     frame?.origin.y = sectionInset.top; 
     atts?.frame = frame!; 
     return atts 
    } 

    let ipPrev = IndexPath(item: indexPath.item - 2, section: indexPath.section) 

    let fPrev = self.layoutAttributesForItem(at: ipPrev)?.frame 

    let rightPrev = (fPrev?.origin.y)! + (fPrev?.size.height)! + 10 

    if (atts?.frame.origin.y)! <= rightPrev { 
     return atts 
    } 

    var f = atts?.frame 
    f?.origin.y = rightPrev 
    atts?.frame = f! 
    return atts 
}