2013-04-06 70 views
24

我將在我的一個項目中創建書架。基本要求是如下:使用UICollectionView創建書架

  • 類似於iBooks書架上
  • 支持兩個方向以及
  • 支持各種iOS設備的孔中(不同的分辨率)
  • 支持刪除和插入項
  • 支撐通過長按手勢對項目進行重新排序
  • 當第一行被拉下時顯示隱藏的標誌

UICollectionView是我想到的第一個選項。它很容易支持網格單元。所以,我用Google搜索了一下,發現了一些非常有用的教程:

Bryan Hansen's UICollectionView custom layout tutorial

Mark Pospesel's How to Add a Decoration View to a UICollectionView

LXReorderableCollectionViewFlowLayout

這裏是結果:(因爲圖形的我選擇的都是請忽略顏色不一致的問題不完美)

enter image description here

我所做的:

  1. 通過創建從UICollectionFlowLayout
  2. 新增用於顯示標誌
  3. 增加了一個裝飾視圖顯示裝飾視圖繼承LXReorderableCollectionViewFlowLayout繼承(用於重新排序的目的)一類的創建一個自定義佈局在bookshelfs

但我遇到了一些問題:

1.我不能在所有的滾動,如果可以在一個屏幕上顯示的項目

然後,我添加以下代碼,使contentsize更大

- (CGSize)collectionViewContentSize 
{ 
    return CGSizeMake(self.collectionView.bounds.size.width,  self.collectionView.bounds.size.height+100); 
} 

那我現在可以滾動。在這裏,我拉下第一行:

enter image description here

你可以看到爲標誌的裝飾視圖工作。

2.但是,我得到了第二組的問題,當我拉起最後一行:

enter image description here

你可以看到裝飾的觀點並沒有在綠框的一部分加入。

3。書架裝飾視圖的背景越來越黑暗。 (請參考same problem here

4.書架欄移動,有時當我重新排列物品

enter image description here

我列出一些重要的代碼在這裏:

- (void)prepareLayout 
{ 
    // call super so flow layout can do all the math for cells, headers, and footers 
    [super prepareLayout]; 

    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 
    NSMutableDictionary *shelfLayoutInfo = [NSMutableDictionary dictionary]; 

    // decoration view - emblem 
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; 
    UICollectionViewLayoutAttributes *emblemAttributes = 
     [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[EmblemView kind] 
      withIndexPath:indexPath]; 
    emblemAttributes.frame = [self frameForEmblem:YES]; 
    dictionary[[EmblemView kind]] = @{indexPath: emblemAttributes}; 

    // Calculate where shelves go in a vertical layout 
    int sectionCount = [self.collectionView numberOfSections]; 

    CGFloat y = 0; 
    CGFloat availableWidth = self.collectionViewContentSize.width - (self.sectionInset.left + self.sectionInset.right); 
    int itemsAcross = floorf((availableWidth + self.minimumInteritemSpacing)/(self.itemSize.width + self.minimumInteritemSpacing)); 

    for (int section = 0; section < sectionCount; section++) 
    { 
     y += self.headerReferenceSize.height; 
     //y += self.sectionInset.top; 

     int itemCount = [self.collectionView numberOfItemsInSection:section]; 
     int rows = ceilf(itemCount/(float)itemsAcross)+1; // add 2 more empty row which doesn't have any data 
     for (int row = 0; row < rows; row++) 
     { 
      indexPath = [NSIndexPath indexPathForItem:row inSection:section]; 
      shelfLayoutInfo[indexPath] = [NSValue valueWithCGRect:CGRectMake(0,y, self.collectionViewContentSize.width, self.itemSize.height + DECORATION_HEIGHT)]; 
      y += self.itemSize.height; 

      if (row < rows - 1) 
       y += self.minimumLineSpacing; 
     } 

     y += self.sectionInset.bottom; 
     y += self.footerReferenceSize.height; 
    } 

    dictionary[[ShelfView kind]] = shelfLayoutInfo; 

    self.shelfLayoutInfo = dictionary; 
} 


- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 
{ 
    NSArray *attributesArrayInRect = [super layoutAttributesForElementsInRect:rect]; 

    // cell layout info 
    for (BookShelfLayoutAttributes *attribs in attributesArrayInRect) 
    { 

     attribs.zIndex = 1; 
     CATransform3D t = CATransform3DIdentity; 
     t = CATransform3DTranslate(t, 0, 0, 40); 
     attribs.transform3D = CATransform3DRotate(t, 15 * M_PI/180, 1, 0, 0); 
    } 

    // Add our decoration views (shelves) 
    NSMutableDictionary* shelfDictionary = self.shelfLayoutInfo[[ShelfView kind]]; 
    NSMutableArray *newArray = [attributesArrayInRect mutableCopy]; 

    [shelfDictionary enumerateKeysAndObjectsUsingBlock:^(id key, NSValue* obj, BOOL *stop) { 

     if (CGRectIntersectsRect([obj CGRectValue], rect)) 
     { 
      UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[ShelfView kind] withIndexPath:key]; 
      attributes.frame = [obj CGRectValue]; 

      NSLog(@"decorationView rect = %@",NSStringFromCGRect(attributes.frame)); 
      attributes.zIndex = 0; 
      //attributes.alpha = 0.5; // screenshots 
      [newArray addObject:attributes]; 
     } 
    }]; 

    attributesArrayInRect = [NSArray arrayWithArray:newArray]; 

    NSMutableDictionary* emblemDictionary = self.shelfLayoutInfo[[EmblemView kind]]; 
    NSMutableArray *newArray2 = [attributesArrayInRect mutableCopy]; 
    [emblemDictionary enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *innerStop) { 
     if (CGRectIntersectsRect(rect, attributes.frame)) { 
      [newArray2 addObject:attributes]; 
     } 
    }]; 

    attributesArrayInRect = [NSArray arrayWithArray:newArray2]; 

    return attributesArrayInRect; 
} 

如果你有足夠的耐心閱讀這篇文章,並提供任何建議或建議,我將不勝感激。如果我能解決所有問題,我會發布完整的源代碼 問題。先謝謝你。

+0

我在蘋果論壇發現了一篇文章。看來DecorationView的重複是一個錯誤。 https://devforums.apple.com/message/773776#773776 – 2013-04-08 00:15:08

+0

作爲prepareLayout函數的一部分,你應該真的計算你的集合視圖的內容大小。就目前而言,無論收集視圖中有多少項,您只能向下滾動100個像素。 – Ash 2016-04-04 11:13:50

回答

0

我會建議檢查你的最後一行,併爲第一行做[self.collectionView ScrollEnable:NO]相同,設置背景顏色清除collectionView和collectionViewCell以及背景視圖上的書架圖像集。