DarkLeafyGreen
DarkLeafyGreen

Reputation: 70436

UITableViewCell drawRect bottom border disappears on insertRow

I have a custom UITableViewCell where I use drawRect to paint a simple bottom border:

override func drawRect(rect: CGRect) {   
   let context = UIGraphicsGetCurrentContext()
   CGContextMoveToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect))
   CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect))
   CGContextSetStrokeColorWithColor(context, UIColor(netHex: 0xEFEEF4).CGColor)
   CGContextSetLineWidth(context, 2)
   CGContextStrokePath(context)
}

This works perfectly. However when I insert a row with animation the borders of ALL cells disappear and appear again when insert animation finishes:

tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: cells.count - 1, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade)

Any idea how to avoid this?

Upvotes: 3

Views: 1409

Answers (2)

Rajan Maheshwari
Rajan Maheshwari

Reputation: 14571

Well You can try this code in tablecell's awakeFromNib if you only want to use CALayers assuming that your TableView is covering the full width of the device.

override func awakeFromNib() {
    super.awakeFromNib()
    let borderLayer = CALayer()
    let lineHeight:CGFloat = 2
    borderLayer.frame = CGRect(x: 0, y: self.frame.height - lineHeight , width: UIScreen.mainScreen().bounds.width, height: lineHeight)
    borderLayer.backgroundColor = UIColor.redColor().CGColor
    self.layer.addSublayer(borderLayer)
}

and you will get the output as: enter image description here

Also make your tableview separator color to clear

self.tableView.separatorColor = UIColor.clearColor()

So that it doesn't gets overlapped with your layer.
What I can observe that now no borders of cells disappears ever whenever a new row is inserted.

Alternatively
We can just use a UIImageView in the cell storyboard and provide a color with the following constraints.
Adding UIImageView
enter image description here

Adding Constraints to UIImageView

enter image description here

And we are done!


There is one more alternate solution to achieve this using Bezier Paths

 override func awakeFromNib() {
    super.awakeFromNib()
    let line = CAShapeLayer()
    let linePath = UIBezierPath()
    linePath.moveToPoint(CGPointMake(0, self.frame.height))
    linePath.addLineToPoint(CGPointMake(UIScreen.mainScreen().bounds.width, self.frame.height))
    line.lineWidth = 3.0
    line.path = linePath.CGPath
    line.strokeColor = UIColor.redColor().CGColor
    self.layer.addSublayer(line)
 }

This also yields the same output.

EDIT:

If we are not using storyboards or nibs for the cell and creating the cell programatically, then we can do a workaround like this:

Create a property in your CustomTableViewCell class

var borderLayer:CALayer!

Now there is a method called layoutSubviews in CustomTableViewCell class

override func layoutSubviews() {
    if(borderLayer != nil) {
        borderLayer.removeFromSuperlayer()
    }
    borderLayer = CALayer()
    let lineHeight:CGFloat = 2
    borderLayer.frame = CGRect(x: 0, y: self.frame.height - lineHeight , width: UIScreen.mainScreen().bounds.width, height: lineHeight)
    borderLayer.backgroundColor = UIColor.redColor().CGColor
    self.layer.addSublayer(borderLayer)
}

Try this out.

Upvotes: 6

sage444
sage444

Reputation: 5684

It's not direct answer, just my suggestion how to achieve equal visual result without drawing.

See example code and result image

@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
    super.viewDidLoad()

    let layer = CALayer()
    let lineHeight:CGFloat = 2
    layer.frame = CGRect(x: 0, y: button.bounds.height - lineHeight , width: button.bounds.width, height: lineHeight)
    layer.backgroundColor = UIColor(colorLiteralRed: 0xEF/255.0, green: 0xEE/255.0, blue: 0xF4/255.0, alpha: 1).CGColor
    button.layer.addSublayer(layer)
}

Button and background view colors configured in IB.

enter image description here

Upvotes: 1

Related Questions