Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 8 UITableView inset: if you have cells with custom layout, you'll probably have this issue too

Tags:

ios

iphone

ipad

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?

like image 725
Jordan Smith Avatar asked Oct 03 '14 12:10

Jordan Smith


4 Answers

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.

like image 158
Matt Avatar answered Oct 11 '22 06:10

Matt


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];

}
like image 44
Jordan Smith Avatar answered Oct 11 '22 04:10

Jordan Smith


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.

like image 32
David Berry Avatar answered Oct 11 '22 05:10

David Berry


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.

like image 40
Fattie Avatar answered Oct 11 '22 04:10

Fattie