2012-12-28 55 views
1

UICollectionViewFlowLayout很棒,但是,我希望它稍微調整一下,以便scrollDirection與佈局方向不同。我想要的例子是跳板主屏幕或表情符號鍵盤,您可以左右滑動,但單元格從左到右,從上到下佈置(而不是從上到下,從左到右,因爲它們是UICollectionViewFlowLayout的scrollDirection設置爲水平)。任何人都知道我可以輕鬆地將FlowLayout子類化以進行此更改?我很失望,他們沒有layoutDirection除了UICollectionViewFlowLayout對象上的scrollDirection :(我可以使用scrollDirection與佈局方向不同的UICollectionViewFlowLayout嗎?

@rdelmar我實現了類似於您的解決方案的東西,並且工作起來(不像我想要的那麼優雅),但我注意到,偶爾項目從收集,除非重新繪製,這就是爲什麼我不接受答案消失,這是我結束了:

@interface UICollectionViewPagedFlowLayout : UICollectionViewFlowLayout 
@property int width; 
@property int height; 
@end 
@implementation UICollectionViewPagedFlowLayout 
#warning MINOR BUG: sometimes symbols disappear 
- (CGSize)collectionViewContentSize { 
    CGSize size = [super collectionViewContentSize]; 
    // make sure it's wide enough to cover all the objects 
    size.width = self.collectionView.bounds.size.width * [self.collectionView numberOfSections]; 
    return size; 
} 
- (NSArray*) layoutAttributesForElementsInRect:(CGRect)rect { 
    NSArray *array = [super layoutAttributesForElementsInRect:rect]; 
    CGRect visibleRect; 
    visibleRect.origin = self.collectionView.contentOffset; 
    visibleRect.size = self.collectionView.bounds.size; 

    for (UICollectionViewLayoutAttributes* attributes in array) { 
     if (CGRectIntersectsRect(attributes.frame, rect)) { 
      // see which section this is in 
      CGRect configurableRect = UIEdgeInsetsInsetRect(visibleRect, self.sectionInset); 
      int horizontalIndex = attributes.indexPath.row % self.width; 
      int verticalIndex = attributes.indexPath.row/self.width; 
      double xspace = (configurableRect.size.width - self.width * self.itemSize.width)/self.width; 
      double yspace = (configurableRect.size.height - self.height * self.itemSize.height)/self.height; 
      attributes.center = CGPointMake(attributes.indexPath.section * visibleRect.size.width + self.sectionInset.left + (self.itemSize.width + xspace) * horizontalIndex + self.itemSize.width/2, self.sectionInset.top + (self.itemSize.height + yspace) * verticalIndex + self.itemSize.height/2); 
     } 
    } 
    return array; 
} 
@end 

回答

1

IIRC,正是這一點是體現在the WWDC 2012 sessions上UICollectionView 。

+1

我重新看了兩個會話並沒有覆蓋的滾動方向獨立於UICollectionViewFlowLayout的佈局。 – Gujamin

1

我不知道輕鬆,取決於你的定義我猜。我做了一個項目w在這裏,我的佈局與您正在尋找的內容非常接近。這將水平放置,從左到右,從上到下。我的數據源是一個數組數組,每個子數組提供一行數據。

#import "SimpleHorizontalLayout.h" // subclass of UICollectionViewFlowLayout 
#define kItemSize 60 

@implementation SimpleHorizontalLayout 


-(CGSize)collectionViewContentSize { 
    NSInteger xSize = [self.collectionView numberOfItemsInSection:0] * (kItemSize + 20); // the 20 is for spacing between cells. 
    NSInteger ySize = [self.collectionView numberOfSections] * (kItemSize + 20); 
    return CGSizeMake(xSize, ySize); 
} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path { 
    UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path]; 
    attributes.size = CGSizeMake(kItemSize,kItemSize); 
    NSInteger xValue = kItemSize/2 + path.row * (kItemSize +20) ; 
    NSInteger yValue = kItemSize + path.section * (kItemSize +20); 
    attributes.center = CGPointMake(xValue, yValue); 
    return attributes; 
} 


-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { 
    NSInteger minRow = (rect.origin.x > 0)? rect.origin.x/(kItemSize +20) : 0; // need to check because bounce gives negative values for x. 
    NSInteger maxRow = rect.size.width/(kItemSize +20) + minRow; 
    NSMutableArray* attributes = [NSMutableArray array]; 
    for(NSInteger i=0 ; i < self.collectionView.numberOfSections; i++) { 
     for (NSInteger j=minRow ; j < maxRow; j++) { 
      NSIndexPath* indexPath = [NSIndexPath indexPathForItem:j inSection:i]; 
      [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; 
     } 
    } 
    return attributes; 
} 
+0

@Gujamin,爲什麼不接受?這應該做你想做的。 – rdelmar

+0

我想實現這一點,爲跳板般的佈局。你的代碼的要點在'layoutAttributesForElementsInRect'中,你交換了部分/行的indeces?還有,你從數據源的'numberOfSection'和'numberOfRowsInSection'返回了什麼? –

+0

@DanF不,該方法中代碼的目的是爲了效率的緣故,爲屏幕上可見的項目調用layoutAttributesForItemAtIndexPath。你可以遍歷數組中的所有項目,它仍然可以工作(但可能會更慢,並使用更多的內存)。 layoutAttributesForItemAtIndexPath方法會執行實際計算以確定每個項目的位置。就我的數據源方法而言,numberOfItemsInSection是[self.theData [section] count],numberOfSections是theData.count – rdelmar

0

直到蘋果增加了一個簡單的標誌,以改變流動佈局的佈局方向,我結束了子類。有些東西是專門針對我的實現,但它可能會幫助別人:

@interface UICollectionViewPagedFlowLayout : UICollectionViewFlowLayout 
@property int width; 
@property int height; 
@end 
@implementation UICollectionViewPagedFlowLayout 
#warning MINOR BUG: sometimes items disappear 
- (CGSize)collectionViewContentSize { 
    CGSize size = [super collectionViewContentSize]; 
    size.width = self.collectionView.bounds.size.width * [self.collectionView numberOfSections]; 
    return size; 
} 
- (NSArray*) layoutAttributesForElementsInRect:(CGRect)rect { 
    NSArray *array = [super layoutAttributesForElementsInRect:rect]; 
    CGRect visibleRect; 
    visibleRect.origin = self.collectionView.contentOffset; 
    visibleRect.size = self.collectionView.bounds.size; 

    for (UICollectionViewLayoutAttributes* attributes in array) { 
     if (CGRectIntersectsRect(attributes.frame, rect)) { 
      // see which section this is in 
      CGRect configurableRect = UIEdgeInsetsInsetRect(visibleRect, self.sectionInset); 
      int horizontalIndex = attributes.indexPath.row % self.width; 
      int verticalIndex = attributes.indexPath.row/self.width; 
      double xspace = (configurableRect.size.width - self.width * self.itemSize.width)/self.width; 
      double yspace = (configurableRect.size.height - self.height * self.itemSize.height)/self.height; 
      attributes.center = CGPointMake(attributes.indexPath.section * visibleRect.size.width + self.sectionInset.left + (self.itemSize.width + xspace) * horizontalIndex + self.itemSize.width/2, self.sectionInset.top + (self.itemSize.height + yspace) * verticalIndex + self.itemSize.height/2); 
     } 
    } 
    return array; 
} 
@end 
相關問題