Spacing between cells on UITableView with Custom UITableViewCell

24,974

Solution 1

If you can't change the cell's height, the solution is to use invisible intermediate cells of the required height. You'll need to recalculate indexes at table view delegate and datasource in that case.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *CELL_ID2 = @"SOME_STUPID_ID2";
    // even rows will be invisible
    if (indexPath.row % 2 == 1)
    {
        UITableViewCell * cell2 = [tableView dequeueReusableCellWithIdentifier:CELL_ID2];

        if (cell2 == nil)
        {
            cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                          reuseIdentifier:CELL_ID2];
            [cell2.contentView setAlpha:0];
            [cell2 setUserInteractionEnabled:NO]; // prevent selection and other stuff
        }
        return cell2;
    }

    [ccTableView setBackgroundColor:[UIColor clearColor]];
    cardsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cardsCell"];

    if(cell == nil){
      NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"cardsCell" owner:self options:nil];
      cell = [topLevelObjects objectAtIndex:0];
    }

     // Use indexPath.row/2 instead of indexPath.row for the visible section to get the correct datasource index (number of rows is increased to add the invisible rows)
        NSString *nmCard = [[self.cards valueForKeyPath:@"cards.name"] objectAtIndex:(indexPath.row/2)];
        cell.descCardLabel.text = nmCard;

      return cell;
    }



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    // two times minus one (invisible at even rows => visibleCount == invisibleCount+1)
    return [[self.cards valueForKeyPath:@"cards"] count] * 2 - 1;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row % 2 == 1)
        return 40;
    return 162;
}

You will also need to recalculate the indexPath.row for :didSelectRowAtIndexPath: and other methods where it is used.

Solution 2

There's actually a pretty easy solution to it that I found, if you're using custom uitableviewcell classes.

In the cell class, add this code:

- (void)setFrame:(CGRect)frame {
    frame.origin.y += 4;
    frame.size.height -= 2 * 4;
    [super setFrame:frame];
}

This will give you a 4pt buffer within the cell height you put into the uitablview class you are calling this cell in. Obviously, you now have to compensate for that less space in the cell when putting in labels and images, but it works. You can also do the same thing on the x-axis to make the width of the cell smaller. I've done this in my app to show background images behind my cells.

Solution 3

Although @A-Live is technically correct, in order to prevent other issues, ex: you forget to put a indexPath.row/2 somewhere, you can do the following (which involves no programming):

Say for example your UITableViewCell height normally is 90 points and you want a 10 point spacing in between each cell. Make your UITableViewCell 100 points high and just make the bottom 10 points of the UITableViewCell blank (no objects of any sort). Then click the UITableViewCell in interface builder and set the backgroundColor to whatever you want the spacing area's color to be.

Voila! You got spacing in between each cell with a little work that is much easier than programming /2 everywhere!

Share:
24,974
gmogames
Author by

gmogames

Just an iOS developer working in beautiful San Diego/CA :)

Updated on July 12, 2022

Comments

  • gmogames
    gmogames almost 2 years

    I have a UITableView loading a custom UITableViewCell from a XIB file. Everything is working fine, but my layout requires that the cells (all inside one single section) have spacing between them. Any chance this can be done without having to raise the ROW height?

    how it is now
    how it is now

    how it's supossed to be
    how it's supossed to be

    EDIT:
    this is how the code is today

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return [[self.cards valueForKeyPath:@"cards"] count];
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        [ccTableView setBackgroundColor:[UIColor clearColor]];
        cardsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cardsCell"];
    
        if(cell == nil){
          NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"cardsCell" owner:self options:nil];
          cell = [topLevelObjects objectAtIndex:0];
        }
    
        NSString *nmCard = [[self.cards valueForKeyPath:@"cards.name"] objectAtIndex:indexPath.row];
        cell.descCardLabel.text = nmCard;
    
      return cell;
    }