【问题标题】:Circle UIView resize with animation keeping Circle shapeCircle UIView调整大小,动画保持圆形
【发布时间】:2017-08-05 20:20:22
【问题描述】:

我有一个 UIView,我将其背景设置为圆形:

 self.colourView.layer.cornerRadius = 350
 self.colourView.clipsToBounds = true

视图是 700 x 700 的正方形。

然后我尝试使用以下方法更改此视图的大小:

UIView.animate(withDuration: zoomLength,
                                   delay: 0,
                                   options: .curveEaseIn,
                                   animations: {
                                    self.colorViewWidth.constant = 100
                                    self.colorViewHeight.constant = 100

                                    self.colourView.layer.cornerRadius = 50
                                    self.colourView.clipsToBounds = true
                                    self.view.layoutIfNeeded()
                                    },
                                   completion: { finished in

                                        })

                                    })

这个问题是视图的圆角半径立即切换到 50。因此,随着视图尺寸的缩小,它看起来不像是一个缩小的圆形,而是一个圆角的正方形,直到它达到 100 x 100 的大小。

如何在动画期间保持圆形形状的同时将圆形视图缩小并缩小。

【问题讨论】:

    标签: ios swift uiview


    【解决方案1】:

    您始终可以在 UIView 动画旁边使用 CABasicAnimation 为圆角半径设置动画。请参阅下面的示例。

    import UIKit
    
    class ViewController: UIViewController {
    
        //cause 'merica
        var colorView = UIView()
        var button = UIButton()
    
        var colorViewWidth : NSLayoutConstraint!
        var colorViewHeight : NSLayoutConstraint!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
    
            colorView.frame = CGRect(x: 0, y: 0, width: 750, height: 750)
            colorView.center = self.view.center
            colorView.backgroundColor = .blue
            colorView.layer.cornerRadius = 350
            colorView.clipsToBounds = true
            colorView.layer.allowsEdgeAntialiasing = true
            colorView.translatesAutoresizingMaskIntoConstraints = false
    
            //set up constraints
    
            colorViewWidth = NSLayoutConstraint(item: colorView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 750)
            colorViewWidth.isActive = true
    
            colorViewHeight = NSLayoutConstraint(item: colorView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 750)
            colorViewHeight.isActive = true
    
            self.view.addSubview(colorView)
            colorView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
            colorView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    
            //button for action
            button = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width - 20, height: 50))
            button.center = self.view.center
            button.center.y = self.view.bounds.height - 70
            button.addTarget(self, action: #selector(ViewController.pressed(sender:)), for: .touchUpInside)
            button.setTitle("Animate", for: .normal)
            button.setTitleColor(.blue, for: .normal)
    
            self.view.addSubview(button)
    
        }
    
        func pressed(sender:UIButton) {
    
            self.colorViewWidth.constant = 100
            self.colorViewHeight.constant = 100
    
            UIView.animate(withDuration: 1.0,
                           delay: 0,
                           options: .curveEaseIn,
                           animations: {
                            self.view.layoutIfNeeded()
    
            },
    
                           completion: { finished in
    
            })
    
            //animate cornerRadius and update model
            let animation = CABasicAnimation(keyPath: "cornerRadius")
            animation.duration = 1.0
            //super important must match
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
            animation.fromValue = colorView.layer.cornerRadius
            animation.toValue = 50
            colorView.layer.add(animation, forKey: nil)
            //update model important
            colorView.layer.cornerRadius = 50
    
        }
    }
    

    结果:

    【讨论】:

      【解决方案2】:

      尝试把你的图片放在 viewDidLayoutSubviews() 中

      override func viewDidLayoutSubviews() {
          super.viewDidLayoutSubviews()
      
       colourView.layer.cornerRadius  = colourView.frame.size.width/2
       colourView.layer.masksToBounds = true
       colourView.layer.borderWidth = 3.0
       colourView.layer.borderColor = UIColor(red: 142.0/255.5, green: 142.0/255.5, blue: 142.0/255.5, alpha: 1.0).cgColor
      
      }
      

      告诉我进展如何

      干杯

      【讨论】:

        【解决方案3】:

        关于动画你需要创建CAShapeLayer对象,然后设置图层对象的cgpath

        let circleLayer = CAShapeLayer()
        let radius = view.bounds.width * 0.5
        //Value of startAngle and endAngle should be in the radian.
        let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        circleLayer.path = path.cgPath
        

        上面将为您绘制圆圈。之后,您可以在layer 对象上应用动画。

        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = fromValue//you can update the value here by default it will be 0
        animation.toValue = toValue //you can update the value here by default it will be 1
        animation.duration = CFTimeInterval(remainingTime)
            circleLayer
        circleLayer.removeAnimation(forKey: "stroke")
        circleLayer.add(animation, forKey: "stroke")
        

        【讨论】:

        • 最干净的解决方案,因为圆的圆角半径代替无论如何都是一个hack。
        • @Mundi 这不会处理任何改变其框架的圆的动画,除非您还对视图进行子类化并在为约束设置动画以保持 shapeLayer 位置时处理 UIView 的边界更改
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-28
        • 1970-01-01
        • 2013-05-04
        • 1970-01-01
        • 1970-01-01
        • 2012-03-12
        相关资源
        最近更新 更多