自定义分隔线在不同设备上的 Y 位置差异

Y Position difference on different devices for custom separator line

我正在屏幕上画一条线以锚定到 FSCalendar 的底部,没什么特别的,但是这条线出现在不同设备上的不同位置(尝试使用物理 iPhone 11 Pro 和几个不同的模拟器. 如果我将它放在一台设备上的正确位置,它会在另一台设备上显得有点高或低。关于为什么会发生这种情况有什么想法吗?

我的代码如下(前导和尾随位置渲染良好)...

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)
  }

}

viewDidLoad() 中的帧不完整 laid-out。

可以将您的电话转到viewDidLayoutSubviews():

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

但是,viewDidLayoutSubviews() 可以而且经常会被多次调用(例如在设备旋转时),并且您的函数每次都会添加一个新的子层。

另一个(可能更好的方法)是添加一个 1 磅高的视图,限制在 calendarView 的底部。

所以,在 viewDidLoad() 你可以这样做:

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),
    ])
}

现在您的“分隔线”将位于日历视图的底部,它将“粘”在底部并调整其宽度if/when 日历视图框架发生变化。