Etranges coins noirs lors de l'utilisation de la fonction draw (_ rect :)
Si je mets le code pour ma fonction UIBezierPath
à l'intérieur, draw(_ rect:)
j'obtiens ces étranges coins noirs très fins autour de la vue et de la queue. Lorsque vous faites glisser la vue (par exemple dans un contrôleur de vue présenté), ces lignes fines commencent également à clignoter. Je suppose que c'est un bug de rendu étrange. Quelqu'un sait-il s'il existe un moyen de résoudre ce problème?

class RenderingView: UIView {
lazy var backgroundView: UIView = {
let view = UIView()
view.layer.cornerRadius = 8
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var shadowView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var textLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Rendering Bug"
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
backgroundColor = .clear
backgroundView.backgroundColor = .yellow
layer.borderWidth = 0
setupLayout()
}
private func setupLayout() {
[shadowView, backgroundView, textLabel].forEach(addSubview)
backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
backgroundView.topAnchor.constraint(equalTo: topAnchor).isActive = true
backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
shadowView.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor).isActive = true
shadowView.topAnchor.constraint(equalTo: backgroundView.topAnchor).isActive = true
shadowView.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor).isActive = true
shadowView.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor).isActive = true
textLabel.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 10).isActive = true
textLabel.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor, constant: -10).isActive = true
textLabel.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 10).isActive = true
textLabel.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -10).isActive = true
}
override func draw(_ rect: CGRect) {
shapeBackground()
}
private func shapeBackground() {
let tailLayer = CAShapeLayer()
let bezierPath = UIBezierPath(roundedRect: CGRect(x: backgroundView.bounds.minX,
y: backgroundView.bounds.minY,
width: backgroundView.bounds.width,
height: backgroundView.bounds.height - 12),
cornerRadius: 8)
let shadowBezierPath = UIBezierPath(roundedRect: CGRect(x: backgroundView.bounds.minX + 5,
y: backgroundView.bounds.minY + 10,
width: backgroundView.bounds.width - 10,
height: backgroundView.bounds.height - 12 - 10),
cornerRadius: 8)
[bezierPath, shadowBezierPath].forEach {
$0.move(to: CGPoint(x: backgroundView.bounds.midX - 12, y: backgroundView.bounds.maxY - 12)) $0.addLine(to: CGPoint(x: backgroundView.bounds.midX, y: backgroundView.bounds.maxY))
$0.addLine(to: CGPoint(x: backgroundView.bounds.midX + 12, y: backgroundView.bounds.maxY - 12)) $0.fill()
$0.close()
}
tailLayer.path = bezierPath.cgPath
tailLayer.fillColor = UIColor.white.cgColor
shadowView.layer.shadowPath = shadowBezierPath.cgPath
shadowView.layer.cornerRadius = 8
backgroundView.layer.masksToBounds = true
backgroundView.layer.mask = tailLayer
}
}
EDIT: Il s'est avéré que j'ai dû utiliser addClip()
les chemins de Bézier pour me débarrasser de ces coins
Réponses
Je ne sais pas si c'est ce que vous visez, mais cela semble parfait lorsque vous déplacez la shapeBackground()
méthode draw(_ rect:)
et effectuez de légères modifications.
J'ai modifié certaines de vos routines de dessin à l'intérieur shapeBackground()
et déplacé la fonction layoutSubviews()
pour calculer la position de la queue à partir du cadre créé par des contraintes. J'ai également ajouté quelques variables pour tailWidth
, & tailHeight
.
Ainsi:
class RenderingView: UIView {
lazy var backgroundView: UIView = {
let view = UIView()
view.layer.cornerRadius = 8
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var shadowView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var textLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "No Rendering Bug"
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
backgroundColor = .clear
backgroundView.backgroundColor = .systemTeal
//backgroundView.frame.size = CGSize(width: 100, height: 100)
layer.borderWidth = 0
setupLayout()
}
private func setupLayout() {
[shadowView, backgroundView, textLabel].forEach(addSubview)
backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
backgroundView.topAnchor.constraint(equalTo: topAnchor).isActive = true
backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
shadowView.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor).isActive = true
shadowView.topAnchor.constraint(equalTo: backgroundView.topAnchor).isActive = true
shadowView.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor).isActive = true
shadowView.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor).isActive = true
textLabel.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 10).isActive = true
textLabel.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor, constant: -10).isActive = true
textLabel.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 10).isActive = true
textLabel.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -10).isActive = true
}
override func didMoveToWindow() {
super.didMoveToWindow()
}
override func layoutSubviews() {
super.layoutSubviews()
shapeBackground(color: UIColor.systemTeal)
}
override func draw(_ rect: CGRect) {
super.draw(rect)
}
private func shapeBackground(color: UIColor) {
let tailLayer = CAShapeLayer()
tailLayer.name = "tailLayer"
let tailWidth: CGFloat = 16
let tailHeight: CGFloat = 10
let bezierPath = UIBezierPath()
let shadowBezierPath = UIBezierPath()
[bezierPath, shadowBezierPath].forEach {
$0.move(to: CGPoint(x: 0, y: 0)) $0.addLine(to: CGPoint(x: tailWidth / 2, y: tailHeight))
$0.addLine(to: CGPoint(x: tailWidth, y: 0)) $0.fill()
$0.close()
}
tailLayer.path = bezierPath.cgPath
tailLayer.fillColor = color.cgColor
shadowView.layer.shadowPath = shadowBezierPath.cgPath
shadowView.layer.cornerRadius = 8
print(backgroundView.bounds.width)
tailLayer.frame = CGRect(x: (backgroundView.bounds.width - tailWidth) / 2,
y: backgroundView.bounds.maxY,
width: tailWidth,
height: tailHeight)
backgroundView.layer.masksToBounds = false
backgroundView.layer.addSublayer(tailLayer)
}
}