user1602074
user1602074

Reputation: 69

collection view or table view

I'm trying to get a simple collection view to work. Basically I would like the collection view to be exactly like a table in a database with rows and columns where I can scroll horizontally. Something like this:

Player 1 cell 1 cell 2 cell 3 cell 4 ... cell 20

Player 2 cell 1 cell 2 cell 3 cell 4 ... cell 20

<----------- scroll --------------------------->

I'm using a collection view so I can determine exactly what cell the player is clicking and it would seem that it would give me more flexibility overall as opposed to a tableview.

The problem is I cannot for the life of me get the collection view to display like I want. The cells are being stacked vertically... example (no way to make them stay in one row and scroll horizontally to see the other columns of the row. example...

Player 1 cell 1 cell 2 cell3

cell 4 cell 6 cell 7 ...

Player 2 cell 1 cell 2 cell4

cell 4...

I'm starting to think that maybe collection view is not a good api to use and maybe I should be simply using a tableview. Any help would be greatly appreciated.

Upvotes: 2

Views: 4592

Answers (3)

kimimaro
kimimaro

Reputation: 1263

UICollectionView is so powerfull and easy to extend because it adds a new feature: UICollectionViewFlowLayout. I'm afraid you cannot get perfect solution for what you need by default implement in Cocoa, but it is so esay to extend the UICollectionViewFlowLayout to a new layout in your case maybe a snake layout.

If any help, maybe you can see this github url: KMCollectionViewSnakeLayout to get some tips. It's not the style like:

Player 1 cell 1 cell 2 cell3

cell 4 cell 6 cell 7 ...

Player 2 cell 1 cell 2 cell4

cell 4...

but is a style like:

Player 1 cell 1 cell 2 | Player 2 cell 1 cell 2

cell3 cell 4 cell 6    | cell3 cell 4 cell6

cell 7 ...             | cell7

Take a while to read it or the Apple Doc, you will got a lot!

Upvotes: 0

rdelmar
rdelmar

Reputation: 104082

Here's my attempt to do this. It works, but as this is my first attempt at a custom layout, I'm sure there are things that could be done to improve it. I made a subclass of UICollectionViewFlowLayout called MultipleLineLayout with this code:

@implementation MultpleLineLayout {
    NSInteger itemWidth;
    NSInteger itemHeight;
}

-(id)init {
    if (self = [super init]) {
        itemWidth = 60;
        itemHeight = 60;
    }
    return self;
}

-(CGSize)collectionViewContentSize {
    NSInteger xSize = [self.collectionView numberOfItemsInSection:0] * (itemWidth + 20) + 60;
    NSInteger ySize = [self.collectionView numberOfSections] * (itemHeight + 20) ;
    return CGSizeMake(xSize, ySize);
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path {
    UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];
    NSInteger xValue;
    if (path.row == 0) {
        itemWidth = 120;
        attributes.size = CGSizeMake(itemWidth,itemHeight);
        xValue = itemWidth/2 + path.row * (itemWidth +20);
    }else{
        itemWidth = 60;
        attributes.size = CGSizeMake(itemWidth,itemHeight);
        xValue = itemWidth/2 + path.row * (itemWidth +20) + 60;
    }
    NSInteger yValue = itemHeight + path.section * (itemHeight +20);
    attributes.center = CGPointMake(xValue, yValue);
    return attributes;
}


-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {
    NSInteger minRow =  (rect.origin.x > 0)?  rect.origin.x/(itemWidth +20) : 0; // need to check because bounce gives negative values  for x.
    NSInteger maxRow = rect.size.width/(itemWidth +20) + minRow;
    NSMutableArray* attributes = [NSMutableArray array];
    for(NSInteger i=0 ; i < self.collectionView.numberOfSections; i++) {
        for (NSInteger j=minRow ; j < maxRow; j++) {
            NSIndexPath* indexPath = [NSIndexPath indexPathForItem:j inSection:i];
            [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
        }
    }
    return attributes;
}

This is the code in the view controller:

#import "ViewController.h"
#import "MultpleLineLayout.h"

@interface ViewController ()
@property (strong,nonatomic) UICollectionView *collectionView;
@property (strong,nonatomic) NSArray *theData;
@end

@implementation ViewController

- (void)viewDidLoad {
    self.theData = @[@[@"Player 1",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20"], @[@"Player 2",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20"],@[@"Player 3",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20"],@[@"Player 4",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20"]];
    MultpleLineLayout *layout = [[MultpleLineLayout alloc] init];
    self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    self.view.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.collectionView];
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];
    [self.collectionView reloadData];
}


- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
    return [self.theData[section] count];
}

- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
    return [self.theData count];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView  cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView  dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    [cell.contentView.subviews.lastObject removeFromSuperview]; //removes the label from a dequeued cell so we can make a new one of the right size.
    UILabel *label;
    if (indexPath.row == 0) {
        label = [[UILabel alloc]initWithFrame:CGRectMake(10, 15, 100, 30)];
    }else{
        label = [[UILabel alloc]initWithFrame:CGRectMake(10, 15, 40, 30)];
    }
    label.backgroundColor = [UIColor yellowColor];
    label.textAlignment = NSTextAlignmentCenter;
    label.text = self.theData[indexPath.section][indexPath.row];
    [cell.contentView addSubview:label];
    cell.backgroundColor = [UIColor orangeColor];
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *item = [collectionView cellForItemAtIndexPath:indexPath];
    NSLog(@"%@",[(UILabel *)item.contentView.subviews.lastObject text]);

}

So, my data is set up as an array of arrays, with each subarray being one player and his scores. This layout does seem to keep each players cells in a horizontal line. I made the first cell of each line bigger to hold the players name -- I'm not sure what's the best way to deal with this one larger cell. I've hard coded some numbers, but that's probably not the best way.

I welcome any suggestions for improvement, or fixes.

Upvotes: 2

JRG-Developer
JRG-Developer

Reputation: 12663

I haven't used this personally, but it seems to be recommended on other SO posts:

https://github.com/TheVole/HorizontalTable

Perhaps this might work better than a UICollectionView ?

(See this post also: How to make a horizontal UI table view on iPhone?)

Good luck!

Upvotes: 0

Related Questions