添加 Line 方法后 Swift Uibezierpath 没有响应
Posted
技术标签:
【中文标题】添加 Line 方法后 Swift Uibezierpath 没有响应【英文标题】:Swift Bezierpath doesnt response after addLine Method 【发布时间】:2020-11-02 11:50:21 【问题描述】:我正在尝试使用 bezierPath 绘制我的视图,而我的代码是?
class auctionCollectionView : UIView
let gradient = CAGradientLayer()
private var shapeLayer: CALayer?
private func addShape()
let shapeLayer = CAShapeLayer()
shapeLayer.path = mys2().cgPath
shapeLayer.strokeColor = UIColor.lightGray.cgColor
self.shapeLayer = shapeLayer
let colorTop = UIColor(hexFromString: "#101820").cgColor
let colorBottom = UIColor(hexFromString: "#101820").cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.mask = shapeLayer
gradientLayer.colors = [colorTop, colorBottom]
gradientLayer.locations = [0.0, 1.0]
gradientLayer.frame = mys2().bounds
self.layer.insertSublayer(gradientLayer, at:0)
override func draw(_ rect: CGRect)
self.addShape()
func mys2() -> UIBezierPath
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: self.frame.height/4)) // start top left
path.addQuadCurve(to: CGPoint(x: self.frame.width , y:self.frame.height/4), controlPoint: CGPoint(x: self.frame.width/2 , y: 0 ))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height * 3/4))
path.addQuadCurve(to: CGPoint(x: 0, y: self.frame.height * 3/4), controlPoint: CGPoint(x: self.frame.width/2, y:self.frame.height / 2))
path.addLine(to: CGPoint(x: 0, y: self.frame.height/4))
path.close()
return path
输出看起来像
我的第一个 QuadCurve 看起来不错,但是当我尝试将其添加到 maxX (self.frame.width)
、maxY ( self.frame.height * 3/4)
到 minX ( 0)
、maxY (self.frame.height * 3/4)
和 CGPoint(x: self.frame.width/2, y:self.frame.height / 2)
时,它的作用就像添加线
我在这里遗漏了什么?问候!
【问题讨论】:
...我将在这里暗中进行猛烈抨击,并说您的问题被否决并标记为已关闭,因为您忘记了对所需结果的描述。从代码中可以看出,但您仍应添加类似“预期结果是底部不是直线,而是类似于顶部的曲线。还应显示渐变而不是黑色。” 我明白了。我这么快就问了这个问题。我忘了解释细节,但你的回答是正确的。谢谢@MaticOblak 【参考方案1】:您的路径似乎没问题,但我担心您的问题是您在覆盖 draw
方法时调用的问题。
您应该先添加层,然后再对其进行管理。或者您应该使用 draw rect 绘制所有内容而不使用图层。在这种情况下,我建议第二个。我不确定您的完整实现应该如何,但是从复制路径并查看渐变代码来看,它可能与以下内容类似:
@IBDesignable class DrawingView: UIView
@IBInspectable var topColor: UIColor? = .red
@IBInspectable var bottomColor: UIColor? = .blue
private func mys2() -> UIBezierPath
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: self.frame.height/4)) // start top left
path.addQuadCurve(to: CGPoint(x: self.frame.width , y:self.frame.height/4), controlPoint: CGPoint(x: self.frame.width/2 , y: 0 ))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height * 3/4))
path.addQuadCurve(to: CGPoint(x: 0, y: self.frame.height * 3/4), controlPoint: CGPoint(x: self.frame.width/2, y:self.frame.height / 2))
path.addLine(to: CGPoint(x: 0, y: self.frame.height/4))
path.close()
return path
override func draw(_ rect: CGRect)
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext(), let topColor = topColor, let bottomColor = bottomColor else
return
// Save because of clipping
context.saveGState()
// Add clipping from my path
mys2().addClip()
let locations: [CGFloat] = [0.0, 1.0]
let colors = [topColor.cgColor, bottomColor.cgColor]
if let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: locations)
context.drawLinearGradient(gradient, start: CGPoint.zero, end: CGPoint(x: 0.0, y: frame.size.height), options: CGGradientDrawingOptions(rawValue: 0))
context.restoreGState()
因此,我们可以使用剪切来代替遮罩,这类似于遮罩在图层中的作用。渐变代码有点不同,但仍然足够相似。
现在请注意,只要视图需要重绘,就会调用此方法。要强制重绘,您需要致电setNeedsDisplay
。因此,以下内容可能很常见:
@IBInspectable var topColor: UIColor? = .red didSet refresh()
@IBInspectable var bottomColor: UIColor? = .blue didSet refresh()
override var frame: CGRect didSet refresh()
override func layoutSubviews()
super.layoutSubviews()
refresh()
private func refresh() setNeedsDisplay()
所以基本上你在以下情况下强制它重绘:
任何颜色都会改变 正在设置框架(不使用自动布局时的常见情况) 正在布局子视图(使用自动布局时的常见情况)请注意,调用setNeedsDisplay
不会立即强制重新加载并调用draw
方法。它只是将组件标记为脏,并将在下一个循环中重新绘制它。结果是draw
只会被调用一次,即使您在同一个循环(堆栈、方法...)中多次调用setNeedsDisplay
。所以不存在性能问题。
在您的情况下,使用图层也可以做到这一点。每当发生变化时,您都需要一个 refresh
方法。那么这个方法应该要么创建子层,要么更正子层帧,掩码......并且应该删除draw
方法。所以要么使用一种方法,要么使用另一种方法,但不能同时使用。
【讨论】:
以上是关于添加 Line 方法后 Swift Uibezierpath 没有响应的主要内容,如果未能解决你的问题,请参考以下文章