I am trying to draw a ruler on top of UIScrollView. The way I do it is by adding a custom view called RulerView. I add this rulerView to superview of scrollView setting its frame to be same as frame of scrollView. I then do custom drawing to draw lines as scrollView scrolls. But the drawing is not smooth, it stutters as I scroll and the end or begin line suddenly appears/disappears. What's wrong in my drawRect?
class RulerView: UIView {
public var contentOffset = CGFloat(0) {
didSet {
self.setNeedsDisplay()
}
}
public var contentSize = CGFloat(0)
let smallLineHeight = CGFloat(4)
let bigLineHeight = CGFloat(10)
override open func layoutSubviews() {
super.layoutSubviews()
self.backgroundColor = UIColor.clear
}
override func draw(_ rect: CGRect) {
UIColor.white.set()
let contentWidth = max(rect.width, contentSize)
let lineGap:CGFloat = 5
let totalNumberOfLines = Int(contentWidth/lineGap)
let startIndex = Int(contentOffset/lineGap)
let endIndex = Int((contentOffset + rect.width)/lineGap)
let beginOffset = contentOffset - CGFloat(startIndex)*lineGap
if let context = UIGraphicsGetCurrentContext() {
for i in startIndex...endIndex {
let path = UIBezierPath()
path.move(to: CGPoint(x: beginOffset + CGFloat(i - startIndex)*lineGap , y:0))
path.addLine(to: CGPoint(x: beginOffset + CGFloat(i - startIndex)*lineGap, y: i % 5 == 0 ? bigLineHeight : smallLineHeight))
path.lineWidth = 0.5
path.stroke()
}
}
}
And in the scrollview delegate, I set this:
//MARK:- UIScrollViewDelegate
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset.x
rulerView.contentSize = scrollView.contentSize.width
rulerView.contentOffset = offset
}
Your
override func draw(_ rect: CGRect)is very "heavy." I think you'll get much better performance by using a shape layer for your "tick marks" and lettingUIKithandle the drawing.Edit - as per comments
Added numbering to the tick marks using
CATextLayeras sublayers.Here's a sample
RulerView(using your tick mark dimensions and spacing):and here's a sample controller class to demonstrate:
Output:
the tick marks (and numbers) will, of course, scroll left-right synched with the scroll view.