【问题标题】:Animate View constraint across arc in IOSIOS中跨弧的动画视图约束
【发布时间】:2021-04-15 19:23:33
【问题描述】:

我想为一个保存进度分数的 UIButton 设置动画, 这是第一个状态

我想将此按钮设置为最终状态

我使用 CAShapeLayer 来制作这些弧线和 我的代码是

   let lineWidth: CGFloat = 12
        let score = 90

        let endAngle : CGFloat = .pi + (.pi * (CGFloat(score)/100))

        let center = view.center

        let progressPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: endAngle, clockwise: true)


        endPoint = progressPath.currentPoint

        let startPoint: CGPoint =  UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi, clockwise: true).currentPoint
  let halfCirclePath = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi*2, clockwise: true)
        let greyLayer = CAShapeLayer()
        greyLayer.strokeColor = greyColor
        greyLayer.lineWidth = lineWidth
        greyLayer.path = halfCirclePath.cgPath
        greyLayer.lineCap = .round
        greyLayer.fillColor = UIColor.clear.cgColor
        greyLayer.shadowColor = UIColor.black.cgColor
        greyLayer.shadowOpacity = 1
        greyLayer.shadowOffset = .zero
        greyLayer.shadowRadius = 2

        view.layer.addSublayer(greyLayer)

        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.lineWidth = lineWidth
        shapeLayer.path = progressPath.cgPath
        shapeLayer.lineCap = .round
        shapeLayer.strokeEnd =  1
        shapeLayer.fillColor = UIColor.clear.cgColor
        view.layer.addSublayer(shapeLayer)

        let label = UILabel()
        label.text = "Best"
        label.textAlignment = .center
        label.textColor = .red
        label.font = UIFont.boldSystemFont(ofSize: 30)

        view.addSubview(label)

        view.layer.addSublayer(label.layer)

        label.translatesAutoresizingMaskIntoConstraints = false

        label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true

        label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

        label.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive  = true

        label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

        view.addSubview(scoreButton)

        scoreButton.setTitle(" \(score)% ", for: .normal)
  scoreButton.layer.masksToBounds = true
        scoreButton.setTitleColor(.blue, for: .normal)
        scoreButton.layer.shadowRadius = 8
        scoreButton.layer.shadowColor = UIColor.black.cgColor
        scoreButton.backgroundColor = .white
        scoreButton.translatesAutoresizingMaskIntoConstraints = false
        scoreButton.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y).isActive = true
        scoreButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x).isActive = true

对于动画,我正在使用 DispatchQueu.main.asyncAfter 但无法更改 ScoreButton 的约束并且它不平滑

 
        let frameCount:CGFloat = 100

        for index in 0...Int(frameCount) {

            DispatchQueue.main.asyncAfter(deadline: .now() + Double(index)/Double(frameCount)) { [self] in
                self.shapeLayer.strokeEnd =  CGFloat(index )/frameCount
                let currentPoint = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi + (.pi * (CGFloat(index)/frameCount)), clockwise: true).currentPoint
                self.scoreButton.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: currentPoint.y).isActive = true
                self.scoreButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: currentPoint.x).isActive = true
                self.view.layoutIfNeeded()
            }
        }

并且发生此错误

[5220:309329] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x600000a20050 H:|-(114.789)-[UIButton:0x140905810' 90% ']   (active, names: '|':UIView:0x140a06100 )>",
    "<NSLayoutConstraint:0x600000a21270 H:|-(314)-[UIButton:0x140905810' 90% ']   (active, names: '|':UIView:0x140a06100 )>"
)

有没有什么流畅的方法来为这个在动画进度中保存分数的 UIButton 设置动画?

【问题讨论】:

    标签: ios swift animation


    【解决方案1】:

    沿曲线路径为视图/图层设置动画的关键是使用关键帧动画。 UIView 和 CALayer 都支持关键帧动画。

    在您的情况下,您应该能够使用视图水平和垂直约束的偏移常量的 UIView 动画。

    您应该能够在线找到有关使用 UIView 关键帧动画沿曲线路径为视图设置动画的教程。

    动画弧需要创建一个 CABAsicAnimation 来动画 CAShapeLayer 的 strokeEnd 属性。同样,网上有各种关于如何做到这一点的教程。 (我最近写了一篇关于使用这种技术动画复选标记的 SO 帖子。)

    【讨论】:

      【解决方案2】:

      你在这里设置约束

        scoreButton.translatesAutoresizingMaskIntoConstraints = false
        scoreButton.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y).isActive = true
        scoreButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x).isActive = true
      

      在此处创建另一个 cconflict 的

       let currentPoint = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi + (.pi * (CGFloat(index)/frameCount)), clockwise: true).currentPoint 
       self.scoreButton.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: currentPoint.y).isActive = true
       self.scoreButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: currentPoint.x).isActive = true
      

      您需要先停用旧的,然后再添加新的,或者仅像这样更改常量

      var bottomCon,leadingCon:NSLayoutConstraint?
      

        scoreButton.translatesAutoresizingMaskIntoConstraints = false
      
        bottomCon = scoreButton.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y)
        bottomCon.isActive = true
      
        leadingCon = scoreButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x) 
        leadingCon.isActive = true
      

       self.bottomCon.constant = currentPoint.y 
       self.leadingCon.constant = currentPoint.x 
       UIView.animate(withDuration: 0.3) {
          self.view.layoutIfNeeded()
       }
      

      【讨论】:

      • Tnx :),效果很好,但不流畅,有没有动画和监控进度的功能?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 2015-09-13
      • 1970-01-01
      • 2013-12-04
      • 2019-02-21
      • 1970-01-01
      相关资源
      最近更新 更多