0

I created a custom UIView subclass. In it, I created a CAShapeLayer as a mask for a CAGradientLayer. I am using Storyboards and with @IBDesignable everything looks ok in the Storyboard. This is how it looks which is perfect:

enter image description here

When I run the app in the Simulator, it does not appear ok:

enter image description here

This is the code which sets this up:

@IBDesignable
class ProgressView: UIView {

let progressLayer = CAShapeLayer()
let gradientLayer = CAGradientLayer()

override func layoutSubviews() {
    super.layoutSubviews()
    setup()
}

func setup() {

    // Setup progress layer.
    progressLayer.lineWidth = 3.0
    progressLayer.fillColor = nil
    progressLayer.strokeEnd = 1
    progressLayer.strokeColor = UIColor.blackColor().CGColor
    progressLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)

    let radius = CGFloat(self.frame.height / 2.5)
    let startAngle = CGFloat(-M_PI / 2)
    let endAngle = CGFloat(3 * M_PI / 2)
    let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

    progressLayer.path = path.CGPath

    layer.addSublayer(progressLayer)


    // Setup gradient layer mask.
    gradientLayer.colors = [Constants.ColorPalette.teal.CGColor, Constants.ColorPalette.orange.CGColor, Constants.ColorPalette.pink.CGColor]
    gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
    gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
    gradientLayer.frame = self.frame
    gradientLayer.mask = progressLayer

    layer.addSublayer(gradientLayer)
}

.....

I've tried changing the frames and using awakeFromNib and required init?(coder aDecoder: NSCoder) to setup the view but it does not seem to work. I want to do everything within the UIView subclass and not a UIViewController.

Any ideas?

JEL
  • 1,540
  • 4
  • 23
  • 51

1 Answers1

0

Have you tried to use layer frame instead of self:

  let radius = CGFloat(layer.frame.height / 2.5)
  ....
  gradientLayer.frame = layer.frame
Alex Kosyakov
  • 2,095
  • 1
  • 17
  • 25
  • Thanks for replying! I just tried your suggestion but it still does not appear in the correct place. It's weird because `@IBDesignable` shows it correctly in Storyboard but in the Simulator it doesn't work. Any other ideas? – JEL Apr 27 '16 at 21:15
  • Maybe this solution will help you: http://stackoverflow.com/questions/2504151/calayers-didnt-get-resized-on-its-uiviews-bounds-change-why – Alex Kosyakov Apr 27 '16 at 21:26
  • Thanks, I tried it but still no good : ( If you have anything else, please let me know. Thanks! – JEL Apr 27 '16 at 21:55
  • did you try it with layer.frame? – Alex Kosyakov Apr 27 '16 at 21:57
  • Yes, I did `progressLayer.frame = layer.bounds` and `progressLayer.frame = self.bounds` inside of `layoutSubviews()`. Is this what you mean? – JEL Apr 27 '16 at 21:58
  • I mean let radius = CGFloat(layer.frame.height / 2.5) gradientLayer.frame = layer.frame – Alex Kosyakov Apr 27 '16 at 21:58
  • Ok yeah I did try `let radius = CGFloat(layer.frame.height / 2.5)` with `progressLayer.frame = layer.bounds` and `progressLayer.frame = self.bounds` . I even removed the `gradientLayer` to make things easier to just deal with the `progressLayer` by itself. – JEL Apr 27 '16 at 22:00
  • This part? let path = UIBezierPath(arcCenter: layer.center.. ? – Alex Kosyakov Apr 27 '16 at 23:12
  • Just tried it, the error was `Value of type CALayer has no member center`. Thanks for all the help so far! Still haven't got it so if you think of anything, please let me know. : ) – JEL Apr 28 '16 at 00:10