1

I have a simple calculator UI in which I'm trying to add a gradient programmatically to the background of the result/output label. Problem is you can only do that using subviews if you still want to show at the front. But when I do this, the UI gets all distorted on screen.

Below are two stackoverflow threads which suggest using subviews for tasks similar to mine:

Adding a CGGradient as sublayer to UILabel hides the text of label

UILabel add GradientLayer

The code I use to add the gradient through subviews is based on the above solutions:

let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRectMake(1, 1, resultLabel.frame.width-2, resultLabel.frame.height-2) //resultLabel.bounds
gradientLayer.colors = [UIColor.greenColor().CGColor as CGColorRef, UIColor.blueColor().CGColor as CGColorRef]
gradientLayer.locations = [0.0, 1.0]

var labelBackground = UIView(frame: resultLabel.frame)
resultLabel.backgroundColor = UIColor.clearColor()
resultLabel.frame = resultLabel.bounds
labelBackground.layer.addSublayer(gradientLayer)
labelBackground.addSubview(resultLabel)

self.view.addSubview(labelBackground)

Although it applies the needed gradient, the display is distorted heavily.

I'm using Swift 2.2 with Xcode 7.3.1

What am I doing wrong ?

Before adding gradient through subviews:

enter image description here

After:

enter image description here

Community
  • 1
  • 1
Ahmad
  • 12,886
  • 30
  • 93
  • 146
  • aren't gradients done at the `CALayer` level? – rolling_codes Jul 23 '16 at 06:23
  • True, but for a UILabel, if you add a CALayer simply as a sublayer, it hides the label text (so you only see the gradient). The subview method is used to add a gradient layer while also keeping the label text in the front. – Ahmad Jul 23 '16 at 15:52
  • Have you tried `insertSublayer(_: CALayer, below: CALayer)` or `insertSublayer(_: CALayer, atIndex: Int)` already? – rolling_codes Jul 23 '16 at 19:28
  • @NoodleOfDeath, that technique doesn't work with UILabels. Anyhow I also confirmed this just now. – Ahmad Jul 23 '16 at 20:01

2 Answers2

1

Try this:

let labelBackground: UIView = UIView(frame: self.resultLabel.frame)
self.resultLabel.backgroundColor = UIColor.clearColor()
self.resultLabel.frame = self.resultLabel.bounds

let gradientLayer: CAGradientLayer = CAGradientLayer()
gradientLayer.frame = labelBackground.layer.bounds
gradientLayer.colors = [UIColor.greenColor().CGColor as CGColorRef, UIColor.blueColor().CGColor as CGColorRef]
gradientLayer.locations = [0.0, 1.0]

labelBackground.layer.addSublayer(gradLayer)
labelBackground.addSubview(self.resultLabel)

self.view.addSubview(labelBackground)
Rigo
  • 523
  • 1
  • 8
  • 22
  • I assume you're suggesting that I add the gradient as a sublayer than as a subview (containing a gradient sublayer). That works but then the label text doesn't appear, which is why I'm trying to use this approach (see the links I mentioned in my question). – Ahmad Jul 23 '16 at 06:40
  • Thanks but it's still not working. I think you only rearranged some of my previous code anyway. – Ahmad Jul 23 '16 at 15:49
0

So I managed to solve this problem myself using a different technique.

I wanted to get a UILabel with a gradient fill in it, WHILE ALSO keeping the text in the UILabel on the front.

To achieve this, I put a UIView object behind the UILabel and made sure the size and coordinates of both of them was the same. I set layout constraints that both of them be the same height and width, and both have the same distance to neighboring elements. I also made the UILabel transparent. After this, I simply added the gradient as a sublayer to the UIView, and it worked wonderfully.

Ahmad
  • 12,886
  • 30
  • 93
  • 146