7
votes

I have a custom UITableViewCell in which I want to draw a vertical separator, similar to the default horizontal ones in iOS7. Currently I use this code when I configure the cell:

UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(cell.contentView.bounds.size.width - rightButtonWidth, 0, 1, cell.contentView.bounds.size.height)];
lineView.backgroundColor = [UIColor lightGrayColor];
lineView.autoresizingMask = 0x3f;
[cell.contentView addSubview:lineView];

As seen in the image, the default separator is rendered at 1 pixel height, whereas mine gets two pixels wide. I tried setting the width to .5 points instead, but then the line is not rendered at all.

Also the color is off, obviously not lightGrayColor. Is there a color constant in UIColor that matches? Edit: the color is RGB 207,207,210 which does not seem to be listed in UIColor.h.

Cell with vertical separator

4
did you try setting the resize mask to 0 (i.e. no resize) ?giorashc
Tried it now, makes no difference.pojo
For the color you can use UIColor colorWithRed:green:blue:alpha methodgiorashc

4 Answers

17
votes

Your problem is because the view will have a width on retina of 2px if the width is set to 1px. What I would suggest is to create a subclass of UIView, let's call it CustomDivider and in -layoutSubviews you will do something like this:

-(void)layoutSubviews {
    [super layoutSubviews];
    if([self.constraints count] == 0) {
        CGFloat width = self.frame.size.width;
        CGFloat height = self.frame.size.height;
        if(width == 1) {
            width = width / [UIScreen mainScreen].scale;
        }
        if (height == 0) {
            height = 1 / [UIScreen mainScreen].scale;
        }

        if(height == 1) {
            height = height / [UIScreen mainScreen].scale;
        }
        self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, width, height);
    }
    else {
        for(NSLayoutConstraint *constraint in self.constraints) {
            if((constraint.firstAttribute == NSLayoutAttributeWidth || constraint.firstAttribute == NSLayoutAttributeHeight) && constraint.constant == 1) {
                constraint.constant /=[UIScreen mainScreen].scale;
            }
        }
    }
}

The code snippet above will check which dimension (width or height) is less or equal to 1 and it will resize it depending on the screen resolution. Also this code will work with autolayout (tested).

This approach will work from IB and from code.

8
votes

Like @danypata did subclass works fine but my situation was to fix exist code quick and simple. Alternatively,

- (CGFloat)defaultOnePixelConversion
{
     return 1.f / [UIScreen mainScreen].scale;
}

then directly apply to the line view.

UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, /*1*/[self defaultOnePixelConversion], height);

the result came out not much different than default UITableView's separator.

0
votes

If you use custom UITableViewCells you can do it via their .xib. Just add a UIView with the color you want, make it one pixel and position it where you want. No need to do it programmatically.

In your code snippet you should add this line:

lineView.clipsToBounds = YES;
0
votes

Here is the swift 4 version:

override func layoutSubviews() {
    super.layoutSubviews()
    if self.constraints.count == 0 {
        var width = self.frame.size.width
        var height = self.frame.size.height
        if width == 1{
            width = width / UIScreen.main.scale

        }
        if height == 0{
            height = 1 / UIScreen.main.scale
        }
        if height == 1 {
            height = height / UIScreen.main.scale
        }
        self.frame = CGRect(x:self.frame.origin.x, y:self.frame.origin.y, width:width, height:height);
    }
    else{
        for constraint:NSLayoutConstraint in self.constraints{
            if(constraint.firstAttribute == NSLayoutAttribute.width || constraint.firstAttribute == NSLayoutAttribute.height) && constraint.constant == 1{
                constraint.constant /= UIScreen.main.scale
            }
        }
    }
}