tableViewの入れ子構造
縦にスクロールするtableViewの特定の行のセルを、横にスクロールするtableViewのコンテンツにしたかったので、方法を調べました。イメージとしては、以下のようになります。
基本的な考え方
基本的には、ViewControllerの中にverticalTableViewがいて、ViewControllerにコントロールを委譲しています。そこでverticalTableViewにverticalTableViewCellを入れます。
verticalTableViewCellには、horizontalTableViewがaddされています。
horizontalTableViewは、 ViewController verticalTableViewCellにコントロールを委譲していて、horizontalTableViewCellを入れています。またhorizontalTableViewのコンテンツおよびスクロール方向を横向きに変更しています。
ViewControllerで2種類のtableViewを制御することになるので、verticalとhorizontalのどちらのtableViewなのかを判別して、処理を分岐させる必要があります。 2つのtableViewを一つのViewControllerで制御するのは複雑なので、修正しました。
私の場合はtagで判別しました。
コード
# import <UIKit/UIKit.h>
# import "VerticalTableViewCell.h"
@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
@property (strong, nonatomic) IBOutlet UITableView *verticalTableView;
@end
# import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// verticalTableViewのdelegate等を設定
self.verticalTableView.delegate = self;
self.verticalTableView.dataSource = self;
// セルの再利用登録
[self.verticalTableView registerClass:[VerticalTableViewCell class]
forCellReuseIdentifier:@"vertical"];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// verticalの場合
// verticalのセルを生成
VerticalTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"vertical"];
[cell buildHorizontalTableView];
// horizontalTableViewに1以上のタグを設定
cell.horizontalTableView.tag = indexPath.row +1;
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 200.0;
}
@end
# import <UIKit/UIKit.h>
@interface VerticalTableViewCell : UITableViewCell
@property (nonatomic, strong) UITableView *horizontalTableView;
- (void)buildHorizontalTableView;
@end
# import "VerticalTableViewCell.h"
@implementation VerticalTableViewCell
- (void)buildHorizontalTableView
{
CGRect frame = CGRectMake(0, 0, 200.0, [UIScreen mainScreen].bounds.size.width);
self.horizontalTableView = [[UITableView alloc] initWithFrame:frame];
// horizontalセルのdelegate等を設定
self.horizontalTableView.delegate = self;
self.horizontalTableView.dataSource = self;
// 横スクロールに変更
self.horizontalTableView.center = CGPointMake(self.horizontalTableView.frame.origin.x + self.horizontalTableView.frame.size.height / 2, self.horizontalTableView.frame.origin.y + self.horizontalTableView.frame.size.width / 2);
self.horizontalTableView.transform = CGAffineTransformMakeRotation(-M_PI / 2);
// セルの再利用登録
[self.horizontalTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"horizontal"];
// tableViewを追加
[self addSubview:self.horizontalTableView];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// horizontalのセルを生成
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"horizontal"];
cell.textLabel.text = [NSString stringWithFormat:@"(%ld,%ld)",tableView.tag -1, indexPath.row];
// セルの向きを横向きに
cell.contentView.transform = CGAffineTransformMakeRotation(M_PI / 2);
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100.0;
}
@end
最後に
今まで1つのviewControllerで2つのtableViewを制御することがなかったので、tableViewとViewControllerは1対1だと思い込んでいました。tableViewCellの中のtableViewのコントロールはどこでやればいいのか分からず悩んでいたのですが、なんとか解決できました。delegateの意味をより理解できた気がします。
2015/02/09追記
やはり一つのviewControllerで2つのtableViewを制御するのは、制御が複雑になるので、よろしくないようです。UITableViewDelegateなどのprotocolをUITableViewCellのカスタムクラスに宣言することで、簡単にできるようです。
参考
(iOS/iPhoneアプリ開発) UITableViewを使って横スクロールビューを作成
[UITableViewまわりのきほん]
(http://qiita.com/mag4n/items/bcdf1e88794317cf8c9c)
リポジトリ