35

Is it possible to keep the contentView.frame always the same, regardless of tableView.editing? I already tried to override layoutSubviews and willTransitionToState but those options fizzled out too. I can't seem to be able to change the width of the contentView. Or maybe my approach ist just plain impossible ... Maybe there is another way to solve this.

The behaviour I want to achieve is the following: I want the standard textLabel of a UITableViewCell to be always indented and not change position when the tableView enters editing mode. The problem I will probably face is that the behaviour of the detailTextLabel will have to be corrected (e.g. truncation of text if textLabelcontent is too long). The reason why I don't want to implement my own UILabelis because a custom subviews will decrease the scrolling performance by a significant amount.

I hope that anyone already implemented something like this in their UITableViewand could show me a solution to this tedious problem. Thanks in advance!

EDIT: I'm dealing with a UITableView in plain and not grouped style.

fscheidl
  • 2,281
  • 3
  • 19
  • 33
  • For me, there was a bug with this. Whenever I would go into editing mode, the indentation would jump around - very odd, very ugly. In the NIB, I had to change the cell's 'style' to something else and then back to 'basic'. Indentation is back to normal now. – Timo Jul 30 '13 at 20:35

9 Answers9

105

Use the UITableViewDelegate method:

- (BOOL)tableView:(UITableView *)tableView 
        shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath 
{

    return NO;
}

This will work for both grouped and non-grouped UITableView types. However, if you have a grouped tableview, you can use this property on the cell:

cell.shouldIndentWhileEditing = NO;
memmons
  • 40,222
  • 21
  • 149
  • 183
Usman.3D
  • 1,791
  • 3
  • 16
  • 27
  • 4
    I already tried this - unfortunately to no avail. In my case, this does not change anything. – fscheidl Apr 26 '11 at 11:29
  • 14
    Apple UITableViewCell Class Reference: shouldIndentWhileEditing `This property has an effect only on table views created in the grouped style (UITableViewStyleGrouped); it has no effect on UITableViewStylePlain table views.` and my table view is indeed of plain style... – fscheidl Apr 26 '11 at 11:40
  • Ah, I just notice that a bit later. You can have two arrays of text labels, one with indentation and the other without indentation. Just when you change the table to editing mode, do it without animation, i.e. animate:NO, and switch your labels array to the one having text without indentation. Do the reverse when you revert back from editing to the normal mode. I hope it helps. – Usman.3D Apr 26 '11 at 11:56
  • Interesting point, but I don't want to add the labels as subview, but rather use the standard textLabels. Another problem this would imply is that there is no animation anymore. – fscheidl Apr 26 '11 at 12:00
  • No need for subviews. Just use the alternate text strings, such as: cell.textLabel.text=@"your label"; => cell.textLabel.text=@"[few spaces go here] your label"; – Usman.3D Apr 26 '11 at 12:18
  • Thanks This worked for me - But then again, I was using the grouped style. – Leddo Dec 13 '11 at 12:12
  • 7
    @Fscheidl `shouldIndentWhileEditingRowAtIndexPath:` does indeed work with both grouped and non-grouped tables. Note that you are referring to the property `shouldIndentWhileEditing` and not the delegate method `shouldIndentWhileEditingRowAtIndexPath`. – memmons Jan 28 '13 at 21:33
  • the delegate methods works; as of iOS 6 the property seems to have no effect regardless of whether you are using grouped or plain style – Christopher King May 22 '13 at 01:20
  • 11
    This should be selected as correct answer, instead of the hacky answer above. – aryaxt Jul 22 '13 at 19:43
  • `shouldIndentWhileEditingRowAtIndexPath` is not called for some reason. My table view has a couple of custom row actions instead of using the default, could it be the reason? – iosdude Apr 25 '17 at 05:42
10

Luckily, iOS is perfectly equipped to keep whatever value constant.

This (ugly) piece of code will keep the frame fixed to whatever value has origin.x==0. This is easily adapted to your particular needs.

// put this in your UITableViewCell subclass
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"observed value for kp %@ changed: %@",keyPath,change);
    if ( [keyPath isEqual:@"frame"] && object == self.contentView )
    {
        CGRect newFrame = self.contentView.frame;
        CGRect oldFrame = [[change objectForKey:NSKeyValueChangeOldKey] CGRectValue];
        NSLog(@"frame old: %@  new: %@",NSStringFromCGRect(oldFrame),NSStringFromCGRect(newFrame));

        if ( newFrame.origin.x != 0 ) self.contentView.frame = oldFrame;
    }
}

// add the cell as an observer for frame changes, somewhere in initialization:
[self.contentView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionOld context:nil];

// IMPORTANT: remove the cell as an observer in -dealloc:
[self.contentView removeObserver:self forKeyPath:@"frame"];

This will only allow the frame to change to values with an origin.x==0. Remove the NSLog() lines for Release builds.

I have tested this for a few minutes and haven't seen any side effect.

mvds
  • 45,755
  • 8
  • 102
  • 111
  • but it crashes in ARC. Error : An instance 0xabd7510 of class UITableViewCellContentView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info: ( Context: 0x0, Property: 0xa9c9b80> ) – Harshit Gupta May 21 '13 at 07:42
  • @harshitgupta you should be able to fix this by putting the removeObserver call somewhere other than dealloc. – mvds May 21 '13 at 09:27
  • Here's a bit of code that I came up with to solve a similar problem that doesn't have the KVO removeObserver issue: http://stackoverflow.com/a/23833468/220338 – hyperspasm May 25 '14 at 03:20
9

Based on Usman.3D

On the storyboard, a property indent While Editing is checked by default. It can be unchecked manually. It equals to cell.shouldIndentWhileEditing = NO.

enter image description here

Community
  • 1
  • 1
AechoLiu
  • 17,522
  • 9
  • 100
  • 118
2

You will have to override layoutSubviews to do this. It applies for the level of custom indentation so it does for none.

Please have a look at How can I change the amount of indentation on my custom UITableViewCell while editing?. I provided an example how to change the level of indentation. Though it didn't work 100% for the OP it worked in my example app. I think this will point you in the right direction.

Community
  • 1
  • 1
Nick Weaver
  • 47,228
  • 12
  • 98
  • 108
  • Amusingly, shortly before asking my question, I studied your code and unfortunately I faced the same problems the OP ran into. To me it seems like any change of the contentView.width property has no effect at all. – fscheidl Apr 26 '11 at 11:48
  • I am sorry to be not of help. – Nick Weaver Apr 26 '11 at 11:51
  • I tried it again and the transformation of the `contentView` is indeed effective. The reason I didn't notice it is that `textLabel` and `detailTextLabel` do not solely rely on `contentView.frame`. – fscheidl Apr 26 '11 at 14:39
2

I had the same trouble with my plain style table even with shouldIndentWhileEditingRowAtIndexPath returning NO

On my side, I encounter the issue because my first row should not be deleted and the rest of the table view cells should.

I added this second method and it worked:

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == 0 && indexPath.section == 0) return NO;

    return YES;    
}

Hope it helps

0

A little late,

but I solved the problem by switching off the Autoresizing Mask for all views in my TableViewCell:

[<viewInCell> setAutoresizingMask:UIViewAutoresizingNone];

Or switch off Autoresizing of width and/or height directly in Interface Builder.

snoersnoer
  • 193
  • 7
0

Just came across this as I was researching the same problem.

A very easy solution is to set the indentation level to a negative number - it is a signed integer after all.

A [cell setIndentationLevel:-3] worked perfectly for me, given a default indentation width of 10, to move the label back to the left in a plain table.

Andy
  • 61
  • 3
0

You can always get a tableviewcell with an indexpath. Using that tableviewcell reuseidentifier, You can avoid the tableview cell content size to be resized or not. I had a requirement to implement the similar kind of functionality to avoid resizing of seperate cells. PFB the code.

-(BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{

BOOL shouldIndentWhileEditingRow = NO;

UITableViewCell *lTableViewCell = [tableView cellForRowAtIndexPath:indexPath];

/*Change the position of the target rect based on Sending messages or Receiving messages*/
if ([lTableViewCell.reuseIdentifier isEqualToString:@"SendingChatCellIdentifier"]) {

    shouldIndentWhileEditingRow = NO;

}else if ([lTableViewCell.reuseIdentifier isEqualToString:@"ReceivingChatCellIdentifier"]){

    shouldIndentWhileEditingRow = YES;
}

return shouldIndentWhileEditingRow;
}
Pradeep Reddy Kypa
  • 3,992
  • 7
  • 57
  • 75
0

Have you looked at UITableViewCell's shouldIndentWhileEditing and indentationLevel properties? Those might sort it.

Steven Kramer
  • 8,473
  • 2
  • 37
  • 43
  • In fact, I already had a look at those methods, but these won't work. If I set the indentationLevel of each cell and the ´UITableView`enters editing mode, the already indented cell is indented even further. – fscheidl Apr 26 '11 at 11:32