前回の続き。今回はセクション分けしてセルを表示する方法です。

サンプル: https://github.com/stack3/UICollectionViewSample

サンプルを起動して、Sectionを選択すると以下の画面が表示されます。

01

02

5つのセクションと1セクションごとに10項目表示されます。

STCustomCollectionSectionViewクラス

セクションのViewはUICollectionReusableViewのSubclassとして作ります。

@interface STCustomCollectionSectionView : UICollectionReusableView

@property (weak, nonatomic, readonly) IBOutlet UILabel *titleLabel;

@end

今回はセクションタイトル表示用のtitleLabelをプロパティとして宣言しています。

STCustomCollectionSectionView.xib

STCustomCollectionSectionViewのレイアウトをxibで作ります。

最初に表示されているViewは削除して、UICollectionReusableViewを配置してください。

03

今回は背景色をグレーにしています。

06-1

ちなみにここでReuse Identifierは設定する必要はありません。

UICollectionReusableViewにタイトル用のUILabelを配置しています。

04

Color(textColorプロパティ)は白、Alignment(textAlignmentプロパティ)は水平方向中心にしてあります。

05-1

xibとSTCustomCollectionSectionViewクラスをひもづけます。xib上のSectionView(UICollectionReusableView)を選択した状態で以下を行います。

Identity InspectorでCustom ClassをSTCustomCollectionSectionViewとする。

08

Connections InspectorでtitleLabelプロパティとひもづける。

07

STSectionSampleViewControllerクラス

UICollectionViewDataSource, UICollectionViewDelegateを実装するように宣言。ここはお約束。

@interface STSectionSampleViewController : UIViewController<UICollectionViewDataSource, UICollectionViewDelegate>

@end

メンバ変数の宣言。

@implementation STSectionSampleViewController {
    // UICollectionView
    IBOutlet __weak UICollectionView *_collectionView;
    // セクションの配列
    __strong NSMutableArray *_sections;
}

initメソッドで_sectionsの初期化。5つのセクションごとに10個のSTCollectionItemオブジェクトを入れます。

        _sections = [NSMutableArray arrayWithCapacity:50];
        for (int j = 0; j < 5; j++) {
            NSMutableArray *items = [NSMutableArray arrayWithCapacity:10];
            for (int i = 0; i < 10; i++) {
                STCollectionItem *item = [[STCollectionItem alloc] init];
                item.number = i+1;
                item.caption = [NSString stringWithFormat:@"caption%d", item.number];
                [items addObject:item];
            }
            [_sections addObject:items];
        }

viewDidLoadで、セルとセクションのViewクラスを登録。

- (void)viewDidLoad
{
    [super viewDidLoad];

    UINib *nib = [UINib nibWithNibName:@"STCustomCollectionViewCell" bundle:nil];
    [_collectionView registerNib:nib forCellWithReuseIdentifier:@"CellId"];

    nib = [UINib nibWithNibName:@"STCustomCollectionSectionView" bundle:nil];
    [_collectionView registerNib:nib forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"Section"];

セクションのクラス登録は、UICollectionView#registerNib:forSupplementaryViewOfKind:withReuseIdentifierを使います。

  • 引数nibにはSTCustomCollectionSectionView.xibから生成したUINibオブジェクト
  • 引数forSupplementaryViewOfKindにはUICollectionElementKindSectionHeader
  • 引数reuseIdentifierは”Section”

を指定します。複数のセクションが表示されますが、すべて同じクラスを使うのでReuseIdentifierはなんでも良いです。今回は”Section”としています。

※ セクションをフッターに表示したい時は、UICollectionElementKindSectionFooterを使います。

dataSourceとdelegateを設定。これもお約束。

    _collectionView.dataSource = self;
    _collectionView.delegate = self;
}

UICollectionViewDataSourceメソッド

セルに関するものは、その1で説明したのと同様なので割愛。

以下のメソッドでセクションの数を返します。

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return _sections.count;
}

以下のメソッドでセクションのViewを返します。

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        STCustomCollectionSectionView *sectionView = [_collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"Section" forIndexPath:indexPath];
        sectionView.titleLabel.text = [NSString stringWithFormat:@"Section%d", indexPath.section + 1];
        return sectionView;
    } else {
        return nil;
    }
}

セルの再利用を考慮してセルのViewを返すメソッドは、UICollectionViewCell#dequeueReusableCellWithReuseIdentifier:forIndexPath:でした。セクションの場合は代わりに、dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:を使います。

セクションのViewを取得したら、titleLabelプロパティを経由して表示するタイトル文字列を指定します。

UICollectionViewDelegateメソッド

その1で説明したように、以下のメソッドで選択したときのAlert表示処理を行います。

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *items = [_sections objectAtIndex:indexPath.section];
    STCollectionItem *item = [items objectAtIndex:indexPath.row];
    NSString *message = [NSString stringWithFormat:@"section:%dn%dn%@", indexPath.section+1, item.number, item.caption];

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
                                                        message:message
                                                       delegate:nil
                                              cancelButtonTitle:nil
                                              otherButtonTitles:@"OK", nil];
    [alertView show];
}

今回はセクションも考慮して適切なSTCollectionItemオブジェクトを取得しています。

以上、セクションの表示でした。
その4へ続く