我有一个自定义按钮,其中CAShapeLayer
添加了draw(_ rect: CGRect)
个circleLayer
。我希望在recording
为true
时隐藏circleLayer
;但是,recording
仅在false
设置为circleLayer
后隐藏。
我注意到的其他一些症状:
class RecordButton: TouchAnimationButton {
var recording: Bool = false {
didSet {
self.setNeedsDisplay()
}
}
private static let ringLayerLineWidthRatio: CGFloat = 0.1
private static let separatorWidthRatio: CGFloat = 0.2
private static let squareLayerCornerRadiusRatio: CGFloat = 0.1
lazy var ringLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.path = UIBezierPath().cgPath
layer.speed = 0.0
layer.strokeColor = UIColor.white.cgColor
layer.fillColor = UIColor.clear.cgColor
return layer
}()
lazy var circleLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.path = UIBezierPath().cgPath
layer.speed = 0.0
layer.fillColor = UIColor.red.cgColor
layer.strokeColor = UIColor.clear.cgColor
layer.lineWidth = 0.0
return layer
}()
lazy var squarePath: CAShapeLayer = {
let layer = CAShapeLayer()
layer.path = UIBezierPath().cgPath
layer.speed = 0.0
layer.fillColor = UIColor.red.cgColor
layer.strokeColor = UIColor.clear.cgColor
layer.lineWidth = 0.0
return layer
}()
func getCirclePath() -> UIBezierPath {
let radius = (getMinDim() - getRingLayerLineWidth() - getSeparatorWidth()) / 2.0
let center = CGPoint(x: self.bounds.size.width / 2.0, y: self.bounds.size.height / 2.0)
let path = UIBezierPath()
path.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: CGFloat(2 * Double.pi), clockwise: true)
return path
}
func getRingPath() -> UIBezierPath {
let center = CGPoint(x: self.bounds.size.width / 2.0, y: self.bounds.size.height / 2.0)
let radius = (getMinDim() - getRingLayerLineWidth()) / 2.0
let path = UIBezierPath()
path.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: CGFloat(2 * Double.pi), clockwise: true)
return path
}
func getSquarePath() -> UIBezierPath {
let radius = (getMinDim() - getRingLayerLineWidth() - 1.5 * getSeparatorWidth()) / 2.0
let center = CGPoint(x: self.bounds.size.width / 2.0, y: self.bounds.size.height / 2.0)
let cornerRadius = RecordButton.squareLayerCornerRadiusRatio * getMinDim()
let side = sqrt(2) * radius
let halfSide = side / 2.0
let path = UIBezierPath()
path.move(to: CGPoint(x: center.x - halfSide + cornerRadius , y: center.y - halfSide))
path.addLine(to: CGPoint(x: center.x + halfSide - cornerRadius, y: center.y - halfSide))
path.addArc(withCenter: CGPoint(x: center.x + halfSide - cornerRadius, y: center.y - halfSide + cornerRadius),
radius: cornerRadius,
startAngle: CGFloat(3.0 * Double.pi / 2.0),
endAngle: CGFloat(2.0 * Double.pi),
clockwise: true)
path.addLine(to: CGPoint(x: center.x + halfSide, y: center.y + halfSide - cornerRadius))
path.addArc(withCenter: CGPoint(x: center.x + halfSide - cornerRadius, y: center.y + halfSide - cornerRadius),
radius: cornerRadius,
startAngle: CGFloat(0),
endAngle: CGFloat(Double.pi / 2.0),
clockwise: true)
path.addLine(to: CGPoint(x: center.x - halfSide + cornerRadius, y: center.y + halfSide))
path.addArc(withCenter: CGPoint(x: center.x - halfSide + cornerRadius, y: center.y + halfSide - cornerRadius),
radius: cornerRadius,
startAngle: CGFloat(Double.pi / 2.0),
endAngle: CGFloat(Double.pi),
clockwise: true)
path.addLine(to: CGPoint(x: center.x - halfSide, y: center.y - halfSide + cornerRadius))
path.addArc(withCenter: CGPoint(x: center.x - halfSide + cornerRadius, y: center.y - halfSide + cornerRadius),
radius: cornerRadius,
startAngle: CGFloat(Double.pi),
endAngle: CGFloat(3.0 * Double.pi / 2.0),
clockwise: true)
return path
}
func getMinDim() -> CGFloat {
return min(self.bounds.size.width, self.bounds.size.height)
}
func getRingLayerLineWidth() -> CGFloat {
return RecordButton.ringLayerLineWidthRatio * getMinDim()
}
func getSeparatorWidth() -> CGFloat {
return RecordButton.separatorWidthRatio * getMinDim()
}
override func draw(_ rect: CGRect) {
super.draw(rect)
if self.squarePath.superlayer == nil {
self.layer.addSublayer(self.squarePath)
}
if self.circleLayer.superlayer == nil {
self.layer.addSublayer(self.circleLayer)
}
if self.ringLayer.superlayer == nil {
self.layer.addSublayer(self.ringLayer)
}
self.ringLayer.lineWidth = getRingLayerLineWidth()
self.ringLayer.path = self.getRingPath().cgPath
self.circleLayer.path = self.getCirclePath().cgPath
self.squarePath.path = self.getSquarePath().cgPath
self.circleLayer.isHidden = self.recording
}
}
class TouchAnimationButton: UIButton {
private static let transformAnimationTime = 0.15
private var initialTransform: CGAffineTransform? = nil
override func layoutSubviews() {
super.layoutSubviews()
self.layer.minificationFilter = kCAFilterTrilinear
if initialTransform == nil {
initialTransform = self.layer.affineTransform()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
weak var weakSelf = self
UIView.animate(withDuration: TouchAnimationButton.transformAnimationTime, animations: {
guard let view = weakSelf, let initialTransform = view.initialTransform else {
return
}
view.layer.setAffineTransform(initialTransform.scaledBy(x: 0.9, y: 0.9))
})
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
weak var weakSelf = self
if let point = touches.first?.location(in: self),
self.bounds.contains(point) {
weak var weakSelf = self
self.layer.shouldRasterize = true
UIView.animate(withDuration: TouchAnimationButton.transformAnimationTime, animations: {
guard let view = weakSelf, let initialTransform = view.initialTransform else {
return
}
view.layer.setAffineTransform(initialTransform.scaledBy(x: 0.9, y: 0.9))
})
} else {
UIView.animate(withDuration: TouchAnimationButton.transformAnimationTime, animations: {
guard let view = weakSelf, let initialTransform = view.initialTransform else {
return
}
view.layer.setAffineTransform(initialTransform)
}, completion: { finished in
weakSelf?.contentScaleFactor = UIScreen.main.scale
})
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
weak var weakSelf = self
UIView.animate(withDuration: TouchAnimationButton.transformAnimationTime, animations: {
guard let view = weakSelf, let initialTransform = view.initialTransform else {
return
}
view.layer.setAffineTransform(initialTransform)
}, completion: { finished in
weakSelf?.contentScaleFactor = UIScreen.main.scale
})
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
weak var weakSelf = self
UIView.animate(withDuration: TouchAnimationButton.transformAnimationTime, animations: {
guard let view = weakSelf, let initialTransform = view.initialTransform else {
return
}
view.layer.setAffineTransform(initialTransform)
}, completion: { finished in
weakSelf?.contentScaleFactor = UIScreen.main.scale
})
}
}
(首次加载视图时)由于此问题会在呈现模式视图控制器然后被解除时自行更正,我相信这只是视图不能正确重绘自身的问题。但是,我似乎无法修复它。
任何帮助都将不胜感激。
{{1}}
答案 0 :(得分:0)
我在baseView上添加了一个CAShapeLayer:
//My Bezier path
let combined = UIBezierPath()
//Create A layer instance
let maskLayer = CAShapeLayer()
//Setting Bounds
maskLayer.frame = baseView.bounds
//Assign a Name to layer that you will add
//This is important as if you want to remove a layer added by you
maskLayer.name = "tailView"
//Assigned my path
maskLayer.path = combined.cgPath
调用此函数以删除CAShapeLayer
func removeLayerFromView(baseView: UIView)
{
if let layer = baseView.layer.mask?.name
{
//Check Layer name
if layer == "tailView"
{
//if yes Remove it
baseView.layer.mask?.removeFromSuperlayer()
}
else
{
//Layer not found
print("Layer not found")
}
}
}
删除UIView中的图层的行
//self.secondMainView name of View from which layer to be Removed
self.removeLayerFromView(baseView: self.secondMainView)
如果视图未更新,则为子类化视图调用SetNeedsDisplay