UITableViewに横スクロールを実装する最良の方法
横に長いUITableViewを考えています。
- Cellは無限に増える可能性がある
- UITableView(UIScrollView)のオリジナルの挙動(慣性スクロールや、バウンス)はそのまま残したい
- 縦横スクロールは1タップで同時に行いたい
- できるだけカスタムクラスは作りたくない
という要件があります。
- オリジナルのViewを作ってそれをScrollViewに貼り付けるという方法では、1. の要件を満たすのが複雑になります。
- ScrollViewの上にTableViewを貼り付けて、縦ScrollはTableViewに、横ScrollはScrollViewにそれぞれ担当させると、一度に一方向へしかScrollが効かず、3. が満たされません。
- TableViewCellの中にScrollViewまたはCollectionViewを乗せても、3. が満たされませんでした。
- ScrollView上にTableViewを乗せそれぞれのUser Interaction EnableをNOにし、さらにその上にPanGestureを設定したUIViewを乗せて、UIViewで感知した縦横のPanGestureをScrollView、TableViewそれぞれに伝達しContentOffsetを操作しましたが、2. が満たされませんでした。
UITableViewの横スクロール問題はよく話題になるかとは思いますが、最善の(最も簡単で、オリジナルUIを継承しつつ、デバイス不可も少ない)方法はどのようなものなのでしょうか。
もし成功されている方がいらっしゃいましたら、アドバイスをお願いいたします。
回答してくださった皆さんのおかげで解決することができました。
結論としては、UICollectionViewを使用し、UICollectionViewLayoutを自作することですべての要件を満たすことができました。
以下、UICollectionViewLayoutのobjcのコードを転載しておきます。
#import "BidirectionalCollectionLayout.h" // UICollectionViewLayoutを継承
@implementation BidirectionalCollectionLayout {
NSInteger cellCount;
CGSize cellSize;
}
- (void)prepareLayout
{
[super prepareLayout];
cellCount = [self.collectionView numberOfItemsInSection:0];
cellSize = CGSizeMake(2000.0f, 66.0f);
}
- (CGSize)collectionViewContentSize {
return CGSizeMake(cellSize.width, cellCount * cellSize.height);
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *indexPathsArray = [self indexPathsForItemsInRect:rect];
NSMutableArray *array = [NSMutableArray array];
for (NSIndexPath *indexPath in indexPathsArray) {
[array addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return array;
}
- (NSArray *)indexPathsForItemsInRect:(CGRect)rect
{
NSMutableArray *array = [NSMutableArray array];
NSInteger minRow = MAX(0, (NSInteger)floor(rect.origin.y / cellSize.height));
NSInteger maxRow = MIN(cellCount, (NSInteger)ceil((rect.origin.y + rect.size.height) / cellSize.height));
for (NSInteger i = minRow; i < maxRow; i++) {
[array addObject:[NSIndexPath indexPathForItem:i inSection:0]];
}
return array;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGFloat offsetY = indexPath.item * cellSize.height;
CGRect frame = CGRectMake(0, offsetY, cellSize.width, cellSize.height);
attributes.frame = frame;
return attributes;
}
@end