CALayer not resizing with Autolayout

后端 未结 2 1626
南方客
南方客 2020-12-14 09:14

I have created a progress bar to be used in a tableView by creating a gradient layer. It works perfectly.

iPhone5:

相关标签:
2条回答
  • 2020-12-14 09:36

    As an alternative to the accepted answer, you could also change the views layer class to be CAGradientLayer. The views layer will always be resized according to layout changes. You can achieve that by subclassing UIView

    class GradientView: UIView {
      override class func layerClass() -> AnyClass {
        return CAGradientLayer.self
      }
    }
    

    then set the colors

    if let gradientLayer = gradientView.layer as? CAGradientLayer {
      gradientLayer.colors = arrayColors
    }
    

    It's less code than adding and maintaining a sublayer, but might not suit all use cases.

    0 讨论(0)
  • 2020-12-14 09:40

    The default layer of a UIView does resize with its view, but sublayers don't (as you found out). One way to make this work is to create a custom view class, move the code you have in your question to it, and override layoutSublayersOfLayer where you can set the gradient layer to be the same size as the view. Because this code is now in a custom class, I also created a property percentageCompleted (instead of a local variable), and added a willSet clause so the bar's appearance is updated any time you change the percentageCompleted property.

    class RDProgressView: UIView {
    
        private let gradient : CAGradientLayer = CAGradientLayer()
    
        var percentageCompleted: Double = 0.0 {
            willSet{
                gradient.locations = [newValue, newValue]
            }
        }
    
        override func awakeFromNib() {
            self.layer.cornerRadius = 4
            self.layer.masksToBounds = true
    
            // create color array
            let arrayColors: [AnyObject] = [
                UIColor (red: 255/255, green: 138/255, blue: 1/255, alpha: 1).CGColor,
                UIColor (red: 110/255, green: 110/255, blue: 118/255, alpha: 1).CGColor]
    
            // set gradient's color array
            gradient.colors = arrayColors
    
            //Set progress(progressBar)
            gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
            gradient.locations = [percentageCompleted, percentageCompleted]
            gradient.endPoint = CGPoint(x: 1, y: 0.5)
    
            self.layer.insertSublayer(gradient, atIndex: 0)
        }
    
        override func layoutSublayersOfLayer(layer: CALayer!) {
            super.layoutSublayersOfLayer(layer)
            gradient.frame = self.bounds
        }
    }
    

    In IB, you would change the class of your view to RDProgressView (in my example), and in cellForRowAtIndexPath, you would only need to get a reference to the view, and set its percentageCompleted property.

    progressBar =  cell.contentView.viewWithTag(3) as RDProgressView! 
    progressBar.percentageCompleted = 0.2
    
    0 讨论(0)
提交回复
热议问题