自定义分隔线在不同设备上的 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 日历视图框架发生变化。
我正在屏幕上画一条线以锚定到 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 日历视图框架发生变化。