2013-06-10 14 views

risposta

0

Immagino che tu stia utilizzando UICollectionViewFlowLayout per impaginare le celle. Non penso che tu possa farlo con un layout di flusso. Probabilmente devi scrivere una sottoclasse personalizzata di UICollectionViewLayout per allineare i bordi superiori di ogni cella.

Questa non è una soluzione molto carina, ma che dire di forzare tutte le celle ad avere le stesse dimensioni e impostare i vincoli nella cella per allineare il contenuto verso l'alto? Questo potrebbe simulare l'aspetto che stai cercando senza dover sottoclasse UICollectionViewLayout.

12

Ho esteso UICollectionViewFlowLayout fornito a UICollectionView. Il seguente override ha funzionato per me.

#import "TopAlignedCollectionViewFlowLayout.h" 

const NSInteger kVerticalSpacing = 10; 

@implementation TopAlignedCollectionViewFlowLayout 

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

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UICollectionViewLayoutAttributes* currentItemAttributes = 
    [super layoutAttributesForItemAtIndexPath:indexPath]; 
    UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout sectionInset]; 
    if (indexPath.item == 0) { 
     CGRect frame = currentItemAttributes.frame; 
     frame.origin.y = sectionInset.top; 
     currentItemAttributes.frame = frame; 

     return currentItemAttributes; 
    } 
    NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section]; 
    CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame; 
    CGFloat previousFrameRightPoint = previousFrame.origin.y + previousFrame.size.height + kVerticalSpacing; 
    CGRect currentFrame = currentItemAttributes.frame; 
    CGRect strecthedCurrentFrame = CGRectMake(currentFrame.origin.x, 
               0, 
               currentFrame.size.width, 
               self.collectionView.frame.size.height 
              ); 
    if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { 
     CGRect frame = currentItemAttributes.frame; 
     frame.origin.y = frame.origin.y = sectionInset.top; 
     currentItemAttributes.frame = frame; 
     return currentItemAttributes; 
    } 
    CGRect frame = currentItemAttributes.frame; 
    frame.origin.y = previousFrameRightPoint; 
    currentItemAttributes.frame = frame; 
    return currentItemAttributes; 
} 

@end 
+0

Ottimo punto di partenza per altre derivazioni dal layout. Ha funzionato come un fascino! –

+1

Ho provato questa soluzione ma non ha funzionato per me con la larghezza della cella statica e l'altezza della cella dinamica. La direzione del flusso è orizzontale. – shujaat

+0

shujaat, lo hai mai capito? – tofutim

3

ho portato questo per Xamarin/MonoTouch per il mio progetto e ho pensato che potrebbe essere utile

public class TopAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout 
{ 
    const int VerticalSpacing = 10; 

    public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(RectangleF rect) 
    { 
     var attributesToReturn = base.LayoutAttributesForElementsInRect(rect); 
     foreach (UICollectionViewLayoutAttributes attributes in attributesToReturn) 
     { 
      if (attributes.RepresentedElementKind == null) 
      { 
       var indexPath = attributes.IndexPath; 
       attributes.Frame = this.LayoutAttributesForItem(indexPath).Frame; 
      } 
     } 
     return attributesToReturn; 
    } 

    public override UICollectionViewLayoutAttributes LayoutAttributesForItem(NSIndexPath indexPath) 
    { 
     var currentItemAttributes = base.LayoutAttributesForItem(indexPath); 
     UIEdgeInsets sectionInset = ((UICollectionViewFlowLayout) this.CollectionView.CollectionViewLayout).SectionInset; 

     if (indexPath.Item == 0) 
     { 
      var frame1 = currentItemAttributes.Frame; 
      frame1.Y = sectionInset.Top; 
      currentItemAttributes.Frame = frame1; 

      return currentItemAttributes; 
     } 

     var previousIndexPath = NSIndexPath.FromItemSection(indexPath.Item - 1, indexPath.Section); 
     var previousFrame = this.LayoutAttributesForItem(previousIndexPath).Frame; 
     var previousFrameRightPoint = previousFrame.Y + previousFrame.Size.Height + VerticalSpacing; 
     var currentFrame = currentItemAttributes.Frame; 
     var strecthedCurrentFrame = new RectangleF(currentFrame.X, 0, currentFrame.Size.Width, this.CollectionView.Frame.Size.Height); 
     if (!previousFrame.IntersectsWith(strecthedCurrentFrame)) 
     { 
      var frame = currentItemAttributes.Frame; 
      frame.Y = frame.Y = sectionInset.Top; 
      currentItemAttributes.Frame = frame; 
      return currentItemAttributes; 
     } 
     RectangleF frame2 = currentItemAttributes.Frame; 
     frame2.Y = previousFrameRightPoint; 
     currentItemAttributes.Frame = frame2; 
     return currentItemAttributes; 
    } 

} 
+0

questo tipo di lavoro (portato su OSX), ma i miei elementi non vanno alla riga successiva – tofutim

+0

c'è qualche malus ricorsivo in questo codice ... – tofutim

Problemi correlati