【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】
UICollectionViewCellで選択表示をさせようと思ってハマったのでメモ。
参考:Collection View プログラミングガイド(iOS用)【PDF】
※P25〜P28あたり。
選択状態をコードで制御するには・・・
たとえば、セルの選択状態をアプリケーション側で描画したい場合は、selectedBackgroundViewプロパティをnilにし、デリゲートオブジェクトに、外観を変更する処理を組み込んでください。
collectionView:didSelectItemAtIndexPath:メソッドに外観を変更する処理、
collectionView:didDeselectItemAtIndexPath:メソッドに元の状態に戻す処理を実装します。
ということらしいので、コードを書いてみた。
//UICollectionViewCell:編集
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell;
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell1" forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
cell.selectedBackgroundView = nil;
//(中略)
return cell;
}
//
-(void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"選択した %@",indexPath);
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
}
-(void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"選択解除した %@",indexPath);
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
}
これだとタップしている間は、背景色が赤に変わるけれど、指を離すと白に戻ってしまう。
で、更に資料を読んでみると・・・
図 2-3に、未選択状態のセルにユーザがタッチしたときに発生する、一連の動作を示します。最初の「タッチダウン」イベントを受けて、コレクションビューはセルの「強調表示」状態をYESにします。もっとも、自動的にセルの外観に反映されるわけではありません。その後、「タッチアップ」イベントが発生すると、「強調表示」状態はNOに戻り、「選択」状態はYESに変わります。ユーザが選択状態を変更すると、コレクションビューはセルのselectedBackgroundViewプロパティに設定されているビューを表示します。コレクションビューが関与してセルの外観を変えるのは、この場合に限ります。ほかの視覚効果はデリゲートオブジェクトが行わなければなりません。
つまり、指を離すと選択状態にはなるものの didUnhighlightItemAtIndexPathが呼ばれて、表示が戻ってしまう・・・ということらしい。
結局、didHighlightItemAtIndexPathとdidUnhighlightItemAtIndexPathは使わず、以下の様に書いて解決。
//UICollectionViewCell:編集
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell;
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell1" forIndexPath:indexPath];
//通常の背景
UIView* backgroundView = [[UIView alloc] initWithFrame:cell.bounds];
cell.backgroundColor = [UIColor whiteColor];
cell.backgroundView = backgroundView;
//選択時の背景
UIView* selectedBGView = [[UIView alloc] initWithFrame:cell.bounds];
selectedBGView.backgroundColor = [UIColor redColor];
cell.selectedBackgroundView = selectedBGView;
//(中略)
return cell;
}
最初のコードで、選択時のイベントハンドラ(didSelectItemAtIndexPath)で選択済表示に変えることもできるけど、それだと選択済項目の表示を戻してやる処理が必要になるので、単一選択ではこれが一番簡単かなと。