Home > other >  Y Position difference on different devices for custom separator line
Y Position difference on different devices for custom separator line

Time:03-01

I am drawing a line on screen to anchor to the bottom of an FSCalendar, nothing special however the line appears in different positions on different devices (attempting with a physical iPhone 11 Pro and a couple different simulators. If I get it at the right position on one device it will appear a bit to high or to low on another. Any ideas as to why this might happen?

My code for the line is as follows (the leading and trailing positions are rendering fine)...

extension UIView {

  let bottom: CGFloat {
      return self.frame.size.height   self.frame.origin.y
  }

  let leading: CGFloat {
    return self.frame.origin.x
  }

  let trailing: CGFloat {
      return self.frame.size.width   self.frame.origin.x
  }
}

class CalendarViewController: UIViewController {

  @IBOutlet var calendar: FSCalendar!

  override func viewDidLoad() {
  drawCalendarSeperatorLine()
  }

  private func drawCalendarSeperatorLine() {
      let path = UIBezierPath()
      let yPosition: CGFloat = calendar.bottom
      let xLeading = view.leading   15
      let xTrailing = view.trailing - 15
      path.move(to: CGPoint(x: xLeading, y: yPosition))
      path.addLine(to: CGPoint(x: xTrailing, y: yPosition))
      let shapeLayer = CAShapeLayer()
      shapeLayer.path = path.cgPath
      shapeLayer.strokeColor = UIColor.separator.cgColor
      shapeLayer.lineWidth = 1
      shapeLayer.opacity = 0.7
      view.layer.addSublayer(shapeLayer)
  }

}

CodePudding user response:

Frames are not completely laid-out in viewDidLoad().

You could move your call to viewDidLayoutSubviews():

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    drawCalendarSeperatorLine()
}

however, viewDidLayoutSubviews() can, and very often will, be called multiple times (such as on device rotation), and your func will be adding a new sublayer every time.

Another (probably better approach) would be to add a 1-pt high view, constrained to the bottom of calendarView.

So, in viewDidLoad() you can do this:

override func viewDidLoad() {
    super.viewDidLoad()

    let sepView = UIView()
    sepView.backgroundColor = UIColor.separator.withAlphaComponent(0.7)
    sepView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(sepView)
    NSLayoutConstraint.activate([
        sepView.leadingAnchor.constraint(equalTo: calendar.leadingAnchor, constant: 15.0),
        sepView.trailingAnchor.constraint(equalTo: calendar.trailingAnchor, constant: -15.0),
        sepView.topAnchor.constraint(equalTo: calendar.bottomAnchor),
        sepView.heightAnchor.constraint(equalToConstant: 1.0),
    ])
}

Now you'll have your "separator line" at the bottom of the calendar view, and it will "stick" to the bottom and resize its width if/when the calendar view frame changes.

  • Related