【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)で選択済表示に変えることもできるけど、それだと選択済項目の表示を戻してやる処理が必要になるので、単一選択ではこれが一番簡単かなと。