ios - 使用 draw(_ rect:) 函数时出现奇怪的黑角
问题描述
如果我将我的代码UIBezierPath
放在draw(_ rect:)
函数内部,我会在视图和尾部周围得到这些奇怪的非常细的黑色角落。当拖动视图时(例如在呈现的视图控制器中),这些细线也开始闪烁。我认为这是一个奇怪的渲染错误。有谁知道是否有办法解决这个问题?
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
}
}
编辑:
原来我不得不addClip()
在贝塞尔路径上使用来摆脱这些角落
解决方案
不确定这是否是您的目标,但是当您将shapeBackground()
方法移出draw(_ rect:)
并进行一些细微修改时,它看起来完美无瑕。
我在里面修改了你的一些绘图例程shapeBackground()
,并将函数移入layoutSubviews()
以根据约束生成的框架计算尾部的位置。tailWidth
我还为, &添加了一些变量tailHeight
。
像这样:
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)
}
}
推荐阅读
- reactjs - 在 React Native 中搜索联系人时,有没有办法避免或改进联系人列表的重新渲染
- mongodb - 猫鼬不能存储双重类型?
- maven - IntelliJ IDEA 在哪里存储“使用项目设置”设置
- go - 从 net/http 包中的 *urlError 访问 Timeout() 方法
- python - 熊猫时间戳年月不能直接访问
- r - 在R中粘贴0常规和斜体文本
- python - 如何使用 python 从网上下载文件?(没有网址)
- python - 使用 Dask 多进程的 HDF5ExtError
- python - QML findChild 来自不同的组件
- sql - SQL - 索引主键 - 性能差异 64bit Int vs 8 char String