UITableViewをツリー上に表示する。第4回目(ツリーの開閉、セルの選択)
前回までで表示部分はだいたい完成したので、今回は動きの部分を実装していきます。
動きとして実装したいのは
- セクション選択時に、セクションが開閉する。
- セルを複数選択可能にする。
まず、セクション選択時の動きですが、セクションが選択されたことを検出し、閉じる動作(配下の非表示)を行わなければなりません。セクション選択の検出は、今回はデリゲートで実装します。
新しくSectionHeaderDelegateプロトコルを作成します。ようはインターフェースを定義したヘッダーファイルです。
#import <Foundation/Foundation.h> @protocol SectionHeaderDelegate <NSObject> @optional -(void)sectionSelected:(int)sectionNo; @end
次に、委譲もとの実装をしていきます。
SectionHeaderを次のように修正します。さきほど作成したSectionHeaderDelegate.hのインポート、デリゲートメソッドを実装する移譲先のクラスへの参照を保持するdelegate_メンバ変数。またその変数にアクセスするためのプロパティ定義を行います。
また、implementationにtouchesBeganメソッドを追加し、デリゲートメソッドを呼び出す実装を記述します。
#import <UIKit/UIKit.h> #import "SectionHeaderDelegate.h" @interface SectionHeader : UIView { @private UILabel* sectionNameLabel_; UIImageView* switchIcon_; UIImage* openImage_; UIImage* closeImage_; __weak NSObject<SectionHeaderDelegate>* delegate_; //ココ } @property(nonatomic) int sectionNo; @property(weak, nonatomic) NSObject<SectionHeaderDelegate>* delegate; //ココ @property(strong, nonatomic, setter=setSectionName:) NSString* sectionName; @property(nonatomic, setter=setSectionOpend:) bool sectionOpend; @end @implementation SectionHeader @synthesize sectionNo = sectionNo_; @synthesize delegate = delegate_; //ココ - (id)initWithFrame:(CGRect)frame { ・ ・ ・ #pragma mark - #pragma mark SectionHeaderDelegate #pragma mark - //ココ - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { if (delegate_ != nil) { if ([delegate_ conformsToProtocol:@protocol(SectionHeaderDelegate)]) { if ([delegate_ respondsToSelector:@selector(sectionSelected:)]) { [delegate_ sectionSelected:sectionNo_]; } } } } @end
これでセクションがタッチされた時に、メソッドを呼ぶ準備ができました。委譲先となるTreeTableViewController側にタッチされた時の動作を記述します。
#import <UIKit/UIKit.h> #import "SectionHeaderDelegate.h" // ココ @interface TreeTableViewController : UITableViewController <SectionHeaderDelegate> { // ココ @private // Data Source NSMutableArray* dataSource_; } @property(strong, nonatomic, setter=setDataSource:) NSMutableArray* dataSource; @end @implementation TreeTableViewController ・ ・ ・ - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionNum { Animals *section = [dataSource_ objectAtIndex:sectionNum]; // カスタムセクションの作成 SectionHeader *sectionView = [[SectionHeader alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 50)]; sectionView.sectionNo = sectionNum; sectionView.sectionName = section.sectionName; sectionView.sectionOpend = section.openFlag; sectionView.delegate = self; // ココ return sectionView; } ・ ・ ・ #pragma mark - #pragma mark CustomSectionViewDelegate #pragma mark - // ココ -(void)sectionSelected:(int)sectionNo { Animals *section = [dataSource_ objectAtIndex:sectionNo]; section.openFlag = !section.openFlag; [self.tableView reloadData]; }
この状態で動かしてみます、セクションをタッチすると開閉するようになりました。だいだい目指すべきことはできましたが、おまけでセルの選択をできるようにしておきます。allowsMultipleSelectionを独自実装します。
#pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // データソースより、そのセルに該当するデータを取得 Animals *section = [dataSource_ objectAtIndex:indexPath.section]; CreatureType *row = [section.types objectAtIndex:indexPath.row]; // 選択された行の選択をON/OFF反転 row.selected = !row.selected; [tableView reloadData]; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // データソースより、そのセルに該当するデータを取得 Animals *section = [dataSource_ objectAtIndex:indexPath.section]; CreatureType *row = [section.types objectAtIndex:indexPath.row]; // 行の選択色変更 ((CustomCell*)cell).cellSelected = row.selected; }
これで、複数選択できるようになりました。
動きなど基本的な部分はこれで完成です。次回で最終回、見栄えを整えて完成といたします。