skip to Main Content

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)

2

Answers


  1. First of all, you do not care about the cell’s frame. You care about its bounds. You need to say

    let frameSize = cell.bounds.size
    

    Also, a great deal depends on when this code runs. You cannot know the correct cell.frame.size until that size has been calculated. You are evidently running this code at a time when it has not yet been calculated (though that’s just a guess, because you didn’t include that information in your question).

    For this reason, it is much better to use a view, not a layer, because the view can be pinned to the cell and will change its size automatically when the cell changes its size. Make the view self-drawing and make it redraw when its size changes. You’ll have a much more robust solution.

    Login or Signup to reply.
  2. 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() {
        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.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search