7

I have made a custom UITableViewCell, and done it properly (adding everything to contentView, and overriding layoutSubviews so my subviews are relative to contentView.bounds).

When the user presses the Edit button, the table indents to allow room for the red delete sign. This is fine, but the default amount of indentation is too much, and ruins the look of my custom cell. How can I reduce the amount of indentation? setIndentationLevel and tableView:IndentationLevelForRowAtIndexPath don't seem to do anything.

(Someone asked a similar question here, but it was never resolved).

Community
  • 1
  • 1
Ric Levy
  • 966
  • 1
  • 15
  • 33

2 Answers2

15

You've got to override layoutSubviews and do something like the following. And don't forget to set the indentation level to something greater than 0 :) For custom cells the indentation level is not applied by default.

To avoid indentation for the single swipe to delete gesture you'll have to do a but more work. There is a state which reflects the editing state of the cell.It is not public but can be accessed with - (void)willTransitionToState:(UITableViewCellStateMask)aState, so storing it in a property does the work for layoutViews.

Apple's documentation for willTransitionToState:

Note that when the user swipes a cell to delete it, the cell transitions to the state identified by the UITableViewCellStateShowingDeleteConfirmationMask constant but the UITableViewCellStateShowingEditControlMask is not set.

header file

int state;

...

@property (nonatomic) int state;

...

cell implementation

@synthesize state;

...

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.contentView.frame = CGRectMake(0,                                          
                                        self.contentView.frame.origin.y,
                                        self.contentView.frame.size.width, 
                                        self.contentView.frame.size.height);

    if (self.editing
        && ((state & UITableViewCellStateShowingEditControlMask)
        && !(state & UITableViewCellStateShowingDeleteConfirmationMask)) || 
            ((state & UITableViewCellStateShowingEditControlMask)
         && (state & UITableViewCellStateShowingDeleteConfirmationMask))) 
    {
        float indentPoints = self.indentationLevel * self.indentationWidth;

        self.contentView.frame = CGRectMake(indentPoints,
                                            self.contentView.frame.origin.y,
                                            self.contentView.frame.size.width - indentPoints, 
                                            self.contentView.frame.size.height);    
    }
}

- (void)willTransitionToState:(UITableViewCellStateMask)aState
{
    [super willTransitionToState:aState];
    self.state = aState;
}
Nick Weaver
  • 47,228
  • 12
  • 98
  • 108
  • Ah... I have noticed one problem. The indentation is the same amount whether the user presses the edit button or swipes to delete. Is there any way of intercepting the swipe-to-delete and telling it to do something different? – Ric Levy Apr 19 '11 at 08:56
  • Ah ok, I just edited my code and provided a simple solution. Have a look. – Nick Weaver Apr 19 '11 at 09:15
  • Ignore what I wrote here a second ago - it works perfectly. Thanks! – Ric Levy Apr 19 '11 at 09:48
  • @Nick sorry - I was right the first time. Unfortunately this doesn't entirely work. The cell now stays still when sliding to delete, and it indents just the right amount when pressing the edit button. But when I press the left-hand red button (to make 'delete' appear on the right), the cell suddenly slips further to the right again. Do you have any idea why this might be? – Ric Levy Apr 19 '11 at 16:36
  • Well it's all a question of the state and the bitmasks. I updated the solution. – Nick Weaver Apr 19 '11 at 16:46
  • @Nick unfortunately with the new code it skips over the 'if' statement every time (I've confirmed by putting an NSLog inside). – Ric Levy Apr 19 '11 at 17:06
  • OK, there was a ! too much in the statement, my fault: corrected it. I tested it and well, funny thing it acted like it, but didn't get into the if body. So this should do it, it only indents when the edit mode is entered but not for a swipe nor if the minus is tapped. – Nick Weaver Apr 19 '11 at 21:16
  • @Nick I'm really sorry to be a pain! It's still doing the 'double indent' thing - it indents a bit when I press Edit, and then some more when I press the round red button. – Ric Levy Apr 20 '11 at 08:23
  • Apple is a pain. So, what I've done doesn't feel comfortable any more, still I don't know of any other way. The problem is the call of the `[super layoutViews]` which indents itself regardless. Without it, the minus won't appear so skipping this is no option. I had to correct the initial indenting and then add a case to keep the cell indented for the case: edit mode entered and minus tapped. I hope this will work for you too. – Nick Weaver Apr 20 '11 at 09:21
  • This is sooooo close to working. Only thing now is that when you swipe-to-delete and then cancel (click elsewhere on the screen) the cell suddenly skips to the left and then slides back as the delete button disappears. – Ric Levy Apr 20 '11 at 10:13
  • Sorry, this is not happening in my working example. You are on your own now. – Nick Weaver Apr 20 '11 at 11:25
1

Nick Weaver's updated answer works great, except for the issue that Rec Levy pointed out:

Only thing now is that when you swipe-to-delete and then cancel (click elsewhere on the screen) the cell suddenly skips to the left and then slides back as the delete button disappears

I ran into the same problem. I'm not sure why it's occurring, but disabling animations while setting the contentView frame resolves it.

...
[UIView setAnimationsEnabled:NO];
self.contentView.frame = CGRectMake(indentPoints,
                                        self.contentView.frame.origin.y,
                                        self.contentView.frame.size.width - indentPoints, 
                                        self.contentView.frame.size.height);
[UIView setAnimationsEnabled:YES];