63

プロジェクトの 1 つで本棚を作成します。基本的な要件は次のとおりです。

  • iBooksの本棚に似ています
  • 両方の向きをうまくサポート
  • あらゆる種類の iOS デバイスを適切にサポート (さまざまな解像度)
  • アイテムの削除と挿入をサポート
  • 長押しジェスチャーによるアイテムの並べ替えをサポート
  • 最初の行がプルダウンされると、非表示のロゴが表示されます

UICollectionView は、私が思いついた最初のオプションです。グリッドセルを簡単にサポートします。それで私はそれをグーグルで調べて、いくつかの非常に役立つチュートリアルを見つけました:

Bryan Hansen の UICollectionView カスタム レイアウト チュートリアル

Mark Pospesel の UICollectionView に装飾ビューを追加する方法

LXReorderableCollectionViewFlowLayout

結果は次のとおりです: (選択したグラフィックはまだ完全ではないため、色の不一致の問題は無視してください。)

ここに画像の説明を入力

私がしたこと:

  1. LXReorderableCollectionViewFlowLayoutUICollectionFlowLayout から継承された (並べ替えの目的で)から継承されたクラスを作成することにより、カスタム レイアウトを作成しました。
  2. ロゴを表示するための装飾ビューを追加
  3. 本棚を表示するための装飾ビューを追加

しかし、私はいくつかの問題に遭遇しました:

1. 一画面に表示できる項目だとスクロールが全くできない

次に、コンテンツサイズを大きくするために、次のコードを追加しました

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

それから私は今スクロールすることができます。ここで、最初の行をプルダウンします。

ここに画像の説明を入力

ロゴの装飾ビューが機能していることがわかります。

2.しかし、最後の行をプルアップすると、2番目の問題が発生しました。

ここに画像の説明を入力

緑色のボックス部分に装飾ビューが追加されていないことがわかります。

3. 本棚の装飾ビューの背景がどんどん暗くなる。(ここで同じ問題を参照してください

4. アイテムを並べ替えると本棚のバーが移動することがある

ここに画像の説明を入力

ここに重要なコードのいくつかをリストします。

- (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;
}

辛抱強くこの投稿を読んで、アドバイスや提案を提供していただければ幸いです。すべての問題を修正できれば、完全なソース コードを投稿します。前もって感謝します。

4

1 に答える 1