Search code examples
iosswiftuikit

How to give margin to dotted line divider in swift?


enter image description here

I want to make the table view divider line dotted and add a margin on the left. The source is below and I tried adjusting the x of shapeRect, botttomShapeLayer.positon, and UIBezierPath, but was not successful. How can I give margin on the left while maintaining the dotted line? Also, the source code below has a space on the right side. Can this space be removed? I solved the problem by adding 100 to the width as a shortcut.

let botttomShapeLayer = CAShapeLayer()
let frameSize = cell.frame.size
let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: 0)

botttomShapeLayer.bounds = shapeRect
botttomShapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height)
botttomShapeLayer.fillColor = UIColor.clear.cgColor
botttomShapeLayer.strokeColor = UIColor.black.cgColor
botttomShapeLayer.lineWidth = 2.0
botttomShapeLayer.lineDashPattern = [4,4]
botttomShapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: shapeRect.height, width: shapeRect.width, height: 0), cornerRadius: 0).cgPath

cell.layer.addSublayer(botttomShapeLayer)

Solution

  • You need to split your code into 2 parts - initialization and update according to current view size, something like this:

    Execute once:

    let dashLayer = CAShapeLayer()
    
    override func awakeFromNib() {
        super.awakeFromNib()
        layer.addSublayer(dashLayer)
        dashLayer.fillColor = UIColor.clear.cgColor
        dashLayer.strokeColor = UIColor.black.cgColor
        dashLayer.lineWidth = 2.0
        dashLayer.lineDashPattern = [4,4]
    }
    

    Then on each layout modify the path:

    override func layoutSubviews() {
        super.layoutSubviews()
        let path = UIBezierPath()
        path.move(to: CGPoint(x: frame.minX + margin, y: frame.maxY - 1.0))
        path.addLine(to: CGPoint(x: frame.maxX, y: frame.maxY - 1.0))
        dashLayer.path = path.cgPath
    }
    
    1. Never trust to frame/bounds during the initialization code, they will change
    2. Never set bounds property unless you really know what you are doing
    3. Usually layers don't really need frame to be set (if you don't want to clip it to bounds), just adding them as a sublayer is enough for them to be visible on the whole parent layer, for CAShapeLayer it's only matters what path is set.