子层未按预期隐藏/显示

时间:2018-01-17 05:50:35

标签: ios swift calayer cashapelayer

我有一个自定义按钮,其中CAShapeLayer添加了draw(_ rect: CGRect)circleLayer。我希望在recordingtrue时隐藏circleLayer;但是,recording仅在false设置为circleLayer后隐藏。

我注意到的其他一些症状:

    首次正确隐藏/显示
  1. 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 }) } } (首次加载视图时)
  2. 如果我提供模态视图控制器然后关闭模态视图控制器,则此行为会自行更正。
  3. 由于此问题会在呈现模式视图控制器然后被解除时自行更正,我相信这只是视图不能正确重绘自身的问题。但是,我似乎无法修复它。

    任何帮助都将不胜感激。

    {{1}}

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