Simple gadget life programming diary

Simple gadget life の中の人によるプログラミングメモ

iOSでセクションタップ方式のアコーディオン型TableViewライブラリを作ってみた。

UIKitのUITableViewだとどこかをクリックすると伸び縮みするようなジャバラの構造にはなっていません。 また、 実現するためにはそこそこのコードを書かなければなりません。
幾つかサンプルのコードがあったけれど、セルの1行目をセクションヘッダーに使っていているものがほとんど。コントローラーが汚れがちで直感的に取り扱えるものでもありません。

そこで、セクションヘッダーをタップすると伸び縮みし、標準のTableViewでコードを書くような間隔で使えるアコーディオン型のTableViewライブラリを作ってみました。(車輪の再発明だと思いますがいい勉強になりました。)

f:id:jtaka1012:20150315102023g:plain

コードはgithubに置いています。
SGLAccordionTableView

できること

・UITableViewと同じメソッド名でセクションの数や列の数、セルの生成、ヘッダーの生成が可能。
delegateとdataSourceを別ファイルに切り出すことも可能。(tableDalegate,tableDataSourceにて指定してください。)
・セクションヘッダーが残らずスクロールさせることが可能。
・ヘッダーがタップされた際にヘッダーのView情報と開閉情報を受け取ることが可能。(アイコンを付け替えたいときなどに使えます。)

できないこと (現在未対応。プルリクエストお待ちしております。。)

・編集モードの使用
・タップをヘッダーの一部分のみに限定する
・コードによる開閉操作

上の動画で使っているコントローラーのコードが以下になります。
スッキリでいつもの通りに使えると思います。
また、_tbl_sampleはstoryBoard上でSGLAccordionTableViewを指定しています。

ポイントはtableDalegate,tableDataSourceの部分。
ここでTableViewで使う情報の取り先を指定しています。名前が違うので注意してください。

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // ** tableDataSource設定後に実施 **/
    // 開閉の初期状態を格納
    NSMutableArray *esArray = [NSMutableArray array];
    
    [esArray insertObject:[NSNumber numberWithBool:YES] atIndex:0];
    [esArray insertObject:[NSNumber numberWithBool:NO] atIndex:1];
    [esArray insertObject:[NSNumber numberWithBool:YES] atIndex:2];
    [esArray insertObject:[NSNumber numberWithBool:NO] atIndex:3];
    [esArray insertObject:[NSNumber numberWithBool:YES] atIndex:4];
    [_tbl_sample setExpandStatus:esArray];

    // セクションヘッダーがスクロールするようにセクションヘッダーの最大値を設定
    _tbl_sample.scrollSectionHeaderHeight = 100;
    
    // delegate設定
    _tbl_sample.tableDelegate = self;
    _tbl_sample.tableDataSource = self;
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 5;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 6;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return 40;
}

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    
    return 50;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, _tbl_sample.frame.size.width, 100)];
    label.backgroundColor = [UIColor lightGrayColor];

    label.text = [NSString stringWithFormat:@"Section%ld", section];
    
    return label;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"myCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }
    
    cell.textLabel.text = [NSString stringWithFormat:@"Row%ld", indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
    return cell;
}

-(void)tableViewSection:(NSInteger)section expanded:(BOOL)expanded headerView:(UIView *)view{
    
    NSLog(@"SectionHeader%ld Tapped!",section);
}

- (IBAction)pushedResetButton:(id)sender {
    
    // セクションの開閉状態を取得
    NSMutableArray *array = _tbl_sample.expandStatusArray;
    
    for (NSNumber *n in array) {
        NSLog(@"値は%d",[n boolValue]);
    }
    
}
@end

よろしければどうぞ。