10

On iOS 8, for larger devices, the default tableView inset seems to change. If you're laying out custom cells and matching their left layout constraint to the default size 15 inset for a cell, your layout will look fine on smaller devices, but on larger devices where the inset changes you'll get something akin to the following:



TableViewCell separator inset alignement



How can I fix this?

Jordan Smith
  • 10,310
  • 7
  • 68
  • 114
  • Can you show us a picture of the issue? – Marcus Adams Oct 03 '14 at 12:15
  • Do you really need to do custom layout for your cells? Your first cell looks like a standard cell with style `UITableViewCellStyleValue1` – Clafou Oct 13 '14 at 13:29
  • 1
    Also, when creating your custom cell, did you add subviews to the `UITableViewCell` itself, or to its `contentView`? I haven't tried it, but I would expect the `contentView` to have a frame that is aligned with the content of standard cells, and the docs do state that subviews should be added to the `contentView`. – Clafou Oct 13 '14 at 13:33
  • @Clafou I probably could use a standard cell. There's plenty of other cells I use where I couldn't though. I add to contentView – Jordan Smith Oct 14 '14 at 06:07
  • Thanks for posting this Jordan! – Fattie Oct 18 '14 at 07:24

7 Answers7

4

There is no option/property in Xcode6 to fix it. There is one setter method setSepratorInset which sets the inset value. But we cannot pass (-ve) value to <#CGFloat left#> to start it from left. As its minimum value is always 0.

[tableView setSeparatorInset:UIEdgeInsetsMake(<#CGFloat top#T, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)];

If you want to get it resolve then hide the separator line and add an imageView of 1px with your desired width to create a line and add it to the cell and that will also look same on every device.

Matt
  • 139
  • 12
3

Managed to write something that seems to work well. If there's a prettier solution, please do share.

@interface InsetRespectingTableViewCell()

@property (nonatomic) IBOutlet NSLayoutConstraint * leftContentInset;
@property (nonatomic) IBOutlet NSLayoutConstraint * rightContentInset;

@end

@implementation InsetRespectingTableViewCell


- (UITableView *)tableView {

    UIView *view;
    for (view = self.superview; ![view isKindOfClass:UITableView.class] && view; view = view.superview);
    return (UITableView *)view;

}

- (void)updateInset {

    CGFloat defaultInset = [self tableView].separatorInset.left;
    self.leftContentInset.constant = defaultInset;
    self.rightContentInset.constant = defaultInset;

}

- (void)didMoveToSuperview {

    [super didMoveToSuperview];
    [self updateInset];

}
Jordan Smith
  • 10,310
  • 7
  • 68
  • 114
  • 2
    For the proper way to do it, check out [this post](http://stackoverflow.com/questions/27420888/uitableviewcell-with-autolayout-left-margin-different-on-iphone-and-ipad) – Eric Jan 23 '16 at 19:49
2

I was able to use size constraints to match the appearance on everything but the iPhone 6+, as long as I stuck with iOS 8. Fixing the appearance on iOS 8 broke it on iOS 7. The basic approach that I used was to set the constraints differently for "Regular Width|Any Height" and use insets of 13 px instead of 7 px:

  1. Lay out your view using auto layout with +/-7 px space to super container.
  2. Select the layout constraint from the list on the left
  3. In the property editor on the far right side, click the (+) next to constant and select "Regular Width | Any Height" from the pop up. That will add a new line under Constant.
  4. Change the value from 7 to 13.

it's not a complete solution, but it's a start.

David Berry
  • 40,941
  • 12
  • 84
  • 95
2

Note - if you need to add a true one pixel line, don't fool with an image, use this:

@interface UILine : UIView
@end

@implementation UILine

-(void)awakeFromNib
    {
    float sortaPixel = 1.0/[UIScreen mainScreen].scale;

    // float sortaPixel = 1.0/self.contentScaleFactor;
    // -- recall, that does NOT work when loading from storyboard!

    UIView *line = [[UIView alloc] initWithFrame:
    CGRectMake(0, 0, self.frame.size.width, sortaPixel)];

    line.userInteractionEnabled = NO;
    line.backgroundColor = self.backgroundColor;

    line.autoresizingMask = UIViewAutoresizingFlexibleWidth;

    [self addSubview:line];

    self.backgroundColor = [UIColor clearColor];
    self.userInteractionEnabled = NO;
    }

@end

How to use in storyboard, just make a UIView that is in the exact place, and exact width, you want. (Naturally, make it stretch to width, or whatever as necessary.)

Just make the view - say - 5 pr 6 pixels high -- purely so you can see it properly. (It does not matter how high you make it on the storyboard.)

(Make the top of the UIView exactly where you want the single-pixel line.)

Make the UIView any color you want, probably black.

Change the class to UILine. At run time it will draw a perfect single-pixel line in the exact location on all devices.

Hope it helps with this in a small way.

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • just a footnote - in modern IB, you could probably use **@IBDesignable** to get this to display as a custom view, more nicely, in storyboard. for objC http://stackoverflow.com/a/24465867/294884 – Fattie Oct 27 '14 at 10:11
1

It's very interesting.

In project created by Xcode5 the left inset of the separator is 15/15/16 (iPhone5s/iPhone6/iPhone6P).

And in project created by Xcode6 is 16/16/20 (iPhone5s/iPhone6/iPhone6P).

In my case, I disable the default separator in the tableView, and made a baseCell to redraw the separatorLine.

link : https://github.com/jshl8612/UTableViewBaseCell

Hopes it helps a little bit.

Steven Jiang
  • 1,006
  • 9
  • 21
0

Here is idea how it can be fixed.

@IBOutlet weak var leftViewLeadingConstraint: NSLayoutConstraint!

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    switch UIScreen.mainScreen().scale {
    case 2:
        leftViewLeadingConstraint.constant = 7.0
    case 3:
        leftViewLeadingConstraint.constant = 11.0
    default:
        assertionFailure("Error: wrong scale value")
    }
}
Konstantin Cherkasov
  • 3,243
  • 2
  • 18
  • 22
  • You want to terminate the app when a new screen scale comes out and you haven't updated your code? Not sure that's a smart idea... also, the accepted answer doesn't rely on self set constants, which could change in future iOS versions. – Jordan Smith Mar 12 '15 at 21:43
  • I know that it is not a perfect solution, but at this moment it works for all iPhone screens. Of course, for iPhone with new scale factor an app should be updated. – Konstantin Cherkasov Mar 13 '15 at 11:06
-1

In your custom cell you can override layoutSubviews and specify the inset you want.

From: https://developer.apple.com/library/IOs/documentation/UIKit/Reference/UIView_Class/index.html#//apple_ref/occ/instm/UIView/layoutSubviews

"You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want"

Zigglzworth
  • 6,645
  • 9
  • 68
  • 107