2015-03-17 18 views
13

Tôi đã tạo một thanh tiến trình sẽ được sử dụng trong một tableView bằng cách tạo một lớp gradient. Nó hoạt động hoàn hảo.CALayer không thay đổi kích thước với Autolayout

iPhone5: enter image description here

Để sử dụng ứng dụng trên nhiều thiết bị, tôi đã tạo ra UIView trong Storyboard, tagged nó và thêm ràng buộc. Tuy nhiên, khi tôi sử dụng ứng dụng trên iPhone 6, CALayer không thay đổi kích thước.

iPhone6: enter image description here

tôi thấy vô cùng ngu ngốc, nhưng không bao giờ tâm trí này. Tôi đã nhìn xung quanh và cố gắng để hiểu làm thế nào để giải quyết điều này trong nhiều tháng, nhưng tôi đã đi lên ngắn. ANYONE có biết cách thay đổi kích thước CALayers bằng UIView không? Bất kỳ trợ giúp sẽ được rất nhiều đánh giá cao ! Cảm ơn bạn.

 progressBar = cell.contentView.viewWithTag(3) as UIView! 
     progressBar.layer.cornerRadius = 4 
     progressBar.layer.masksToBounds = true 


     // create gradient layer 
     let gradient : CAGradientLayer = CAGradientLayer() 

     // 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 frame bounds to match progressBar bounds 
     gradient.frame = progressBar.bounds 

     // set gradient's color array 
     gradient.colors = arrayColors 

     //Set progress(progressBar) 
     var percentageCompleted = 0.6 

     gradient.startPoint = CGPoint(x: 0.0, y: 0.5) 
     gradient.locations = [percentageCompleted, percentageCompleted] 
     gradient.endPoint = CGPoint(x: 1, y: 0.5) 

     // replace base layer with gradient layer 
     progressBar.layer.insertSublayer(gradient, atIndex: 0) 

Trả lời

44

Lớp mặc định của UIView thay đổi kích thước với chế độ xem nhưng lớp con không (như bạn đã tìm thấy). Một cách để thực hiện công việc này là tạo một lớp xem tùy chỉnh, di chuyển mã bạn có trong câu hỏi của bạn đến nó và ghi đè layoutSublayersOfLayer nơi bạn có thể đặt lớp gradient có cùng kích thước với chế độ xem. Vì mã này hiện đang ở trong một lớp tùy chỉnh, tôi cũng đã tạo một thuộc tính percentCompleted (thay vì một biến cục bộ) và thêm một mệnh đề willSet để hình dạng của thanh được cập nhật bất cứ khi nào bạn thay đổi thuộc tính percentCompleted.

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 
    } 
} 

Trong IB, bạn sẽ thay đổi lớp của xem của bạn để RDProgressView (trong ví dụ của tôi), và trong cellForRowAtIndexPath, bạn sẽ chỉ cần phải nhận được một tham chiếu đến xem, và thiết lập thuộc tính percentageCompleted của nó.

progressBar = cell.contentView.viewWithTag(3) as RDProgressView! 
progressBar.percentageCompleted = 0.2 
+0

Cảm ơn bạn rất nhiều - nó hoạt động hoàn hảo. Bạn trả lời xong, giải pháp thanh lịch và nó giải quyết được vấn đề của tôi. Hôm nay tôi sẽ tìm hiểu về awakeFromNib và willSet. Cám ơn bạn một lần nữa! (Oh và tôi thụt dòng đầu tiên và cuối cùng của khối đầu tiên của mã và instantiated ProgressBar bằng cách thêm chúng) – KML

11

Để thay thế cho câu trả lời được chấp nhận, bạn cũng có thể thay đổi lớp lớp lượt xem thành CAGradientLayer. Lớp lượt xem sẽ luôn được thay đổi kích thước theo thay đổi bố cục. Bạn có thể đạt được điều đó bằng cách subclassing UIView

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

sau đó thiết lập các màu sắc

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

Đó là mã ít hơn vì thêm và duy trì một lớp con, nhưng có thể không phù hợp với tất cả các trường hợp sử dụng.

+0

override lớp var layerClass: AnyClass { trở CAGradientLayer.self } override var lớp: CAGradientLayer { trở super.layer như! CAGradientLayer } – lastcc

+0

Sạch hơn nhiều. Bạn có thể đặt tên cho bất kỳ trường hợp sử dụng nào mà bạn cho rằng phương pháp này có thể không phù hợp? – keeshux

Các vấn đề liên quan