#ios #view #calayer #uibezierpath
#iOS #Вид #calayer #uibezierpath
Вопрос:
Я добавляю круговой слой вокруг моего кругового вида и устанавливаю его position
в центр вида, но слой добавляется в другом положении. Ниже приведен код.
class CustomView: UIView {
let outerLayer = CAShapeLayer()
required init?(coder: NSCoder) {
super.init(coder: coder)
self.layer.addSublayer(outerLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
self.backgroundColor = UIColor.systemBlue
self.layer.cornerRadius = self.bounds.height/2
self.layer.borderWidth = 2.0
self.layer.borderColor = UIColor.white.cgColor
let outerLayerFrame = self.bounds.insetBy(dx: -5.0, dy: -5.0)
outerLayer.frame = outerLayerFrame
let path = UIBezierPath(ovalIn: outerLayerFrame)
outerLayer.path = path.cgPath
outerLayer.position = self.center
outerLayer.strokeColor = UIColor.systemBlue.cgColor
outerLayer.fillColor = UIColor.clear.cgColor
outerLayer.lineWidth = 3
}
}
Может кто-нибудь, пожалуйста, сказать мне, что здесь не так.
Ответ №1:
Вы хотите установить свойства своего слоя (ов) при создании экземпляра / инициализации вида, но его размер может (и обычно меняется) изменяться между тем и когда автоматическая компоновка настраивает его в соответствии с текущими размерами устройства.
В отличие от UIView
самого по себе, слои не изменяют размер автоматически.
Итак, вы хотите задать контуры обрамления и слоев в layoutSubviews()
:
class CustomView: UIView {
let outerLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}
// layoutSubviews is where you want to set your size
// and corner radius values
override func layoutSubviews() {
super.layoutSubviews()
// make self "round"
self.layer.cornerRadius = self.bounds.height/2
// add a round path for outer layer
let path = UIBezierPath(ovalIn: bounds)
outerLayer.path = path.cgPath
}
private func configure() {
self.backgroundColor = UIColor.systemBlue
// setup layer properties here
self.layer.borderWidth = 2.0
self.layer.borderColor = UIColor.white.cgColor
outerLayer.strokeColor = UIColor.systemBlue.cgColor
outerLayer.fillColor = UIColor.clear.cgColor
outerLayer.lineWidth = 3
// add the sublayer here
self.layer.addSublayer(outerLayer)
}
}
Результат (для вида установлено значение 120 x 120 точек):
Комментарии:
1. Я знаю, я только предполагал внести изменения, связанные с рамками и границами, в layoutSubviews. У меня просто было это в одном месте, чтобы разобраться со своей проблемой. Однако, увидев ваш код, я понял, что мне никогда не приходилось указывать позицию. Установления границ было бы достаточно. Спасибо вам за лучшее решение.
Ответ №2:
Итак, я понял, что именно из-за положения слой не выровнен по центру.
Вот решение, я подумал-
class CustomView: UIView {
let outerLayer = CAShapeLayer()
required init?(coder: NSCoder) {
super.init(coder: coder)
self.layer.addSublayer(outerLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
self.backgroundColor = UIColor.systemBlue
self.layer.cornerRadius = self.bounds.height/2
self.layer.borderWidth = 2.0
self.layer.borderColor = UIColor.white.cgColor
let outerLayerBounds = self.bounds.insetBy(dx: -5.0, dy: -5.0)
outerLayer.bounds = outerLayerBounds // should be bounds not frame
let path = UIBezierPath(ovalIn: outerLayerBounds)
outerLayer.path = path.cgPath
outerLayer.position = CGPoint(x: outerLayerBounds.midX , y: outerLayerBounds.midY) //self.center doesn't center the layer, had to calculate the center of the layer manually
outerLayer.strokeColor = UIColor.systemBlue.cgColor
outerLayer.fillColor = UIColor.clear.cgColor
outerLayer.lineWidth = 3
}
}