Swift Button.setText doesn't work with gradient - ios

I'm new in Swift and I have a problem. my button do not set the text if I try to use the gradient. here is my code:
let gradient:CAGradientLayer = CAGradientLayer()
let colorBottom = UIColor(red: 9/255.0, green: 137/255.0, blue: 133/255.0, alpha: 1.0).CGColor
let colorTop = UIColor(red: 222.0/255.0, green: 255.0/255.0, blue: 201.0/255.0, alpha: 1.0).CGColor
gradient.colors = [colorTop, colorBottom]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.frame = LoginButton.bounds
gradient.cornerRadius = 25.0
LoginButton.layer.addSublayer(gradient)
LoginButton.setTitle("Login", forState: UIControlState.Normal)
LoginButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
self.view.addSubview(LoginButton)

Adding a sublayer works the same as adding a subview so adding the gradient layer may be covering the other layers where the text is drawn.
If you remove this line does it work?
LoginButton.layer.addSublayer(gradient)
If it does, try seeing how many layers are in LoginButton.layer.sublayers and try inserting the gradient layer behind one of those sublayers (wherever it looks the best) using one of the following methods:
-insertSublayer:above:
-insertSublayer:below:
-insertSublayer:atIndex:

This line is the problem:
LoginButton.layer.addSublayer(gradient)
Do not add any extra layers to a UIButton. It already knows how to draw itself. If you want it to have a gradient background, draw the gradient into an image and set that as the button's background image in the normal way.
Or make the button clear and put the gradient layer behind the button (though this is not as good).

Related

Apply CAGradientLayer to layer.borderColor

I'm trying to implement a underlined UITextField with a gradient. Therefore I created a extension with a function underlined().
To get a gradient, I created a CAGradientLayer and made these customizations:
func underlined(){
let color = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1).cgColor
let sndColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1).cgColor
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [color, sndColor]
gradient.locations = [0.0, 1.0]
gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 0)
let width = CGFloat(2.0)
gradient.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
gradient.borderWidth = width
self.layer.insertSublayer(gradient, at: 0)
self.layer.masksToBounds = true
}
A underline is being displayed, but it solely solid black - I've tried to change the colors, but it remains black (Issue outdated - see edit).
Does anybody see the issue?
Edit:
Adding gradient.borderColor = UIColor.blue.cgColor let me change the color of the line - but how can I apply the gradient on the border color?
Remove the below line from your code:
gradient.borderWidth = width
Screenshot:
Your code was not working because, the borderWidth is covering whole of the gradient frame.Try setting the borderColor, then you'll see the difference.
gradient.borderColor = UIColor.red.cgColor
Let me know if you still face any issues.

CAGradientLayer: other UIObjects not showing up

When I use the CAGradientLayer on iOS to set up gradient for my viewcontroller, objects that I had previously placed using my interface builder are not showing up. When I take the gradientLayer function away, these objects show up. Also, when I add these objects programatically as a subview they show up in the iOS simulator. What's going on? Here is my gradientLayer code:
func setUpGradient(){
let topColor=UIColor(red: 255/255, green: 149/255, blue: 56/255,alpha: 1)
let bottomColor=UIColor(red: 216/255, green: 57/255, blue: 177/255,
alpha: 1)
let gradientColors: [CGColor]=[topColor.cgColor,bottomColor.cgColor]
var gradientLayer = CAGradientLayer()
gradientLayer.frame = self.view.bounds
gradientLayer.colors=gradientColors
gradientLayer.startPoint=CGPoint(x: 0, y:0)
gradientLayer.endPoint=CGPoint(x: 0, y:1)
self.view.layer.addSublayer(gradientLayer)
}
The reason is simple which is the gradient layer covers all the elements when you add them in IB by this line
self.view.layer.addSublayer(gradientLayer)
so you may insert it below them like this
self.view.layer.insertSublayer(gradientLayer,at:0)

Adding a gradient layer on top of a UIButton's backgroundImage

I've got a project with some buttons that are in a UIStackView. Each of the buttons has a backgroundImage. Everything renders as desired, but I'd like to put a gradient layer in front of the backgroundImage that's semi-transparent so the text on the button has a little more contrast.
I'm attempting to use this code in viewDidLoad to add a semi-transparent gradient on front of each UIButton's backgroundImage:
buttonArray = [buttonOne, buttonTwo, buttonThree, buttonFour]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor(white: 1.0, alpha: 0.5)]
// gradientLayer.colors = [UIColor(white: 1.0, alpha: 0.5).cgColor]
// gradientLayer.colors = [UIColor.orange]
// gradientLayer.colors = [UIColor.orange.cgColor]
buttonArray.forEach({$0.imageView?.layer.insertSublayer(gradientLayer, at: 0)})
As it stands, nothing gets added. I tried changing the color to something without a alpha value and changing the desired color to a .cgColor. No dice. Thank you for reading. I welcome your suggestions how to put a gradientLayer in front of a UIButton's backgroundImage.
I based my attempt off code found here
I think you have to specify more than one color, as well as the bounds of the layer:
let buttonArray = [buttonOne, buttonTwo, buttonThree, buttonFour]
for button in buttonArray {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor(white: 0.5, alpha: 0.5).cgColor, UIColor(white: 1.0, alpha: 0.5).cgColor]
gradientLayer.frame = (button?.bounds)!
button?.layer.insertSublayer(gradientLayer, at: 0)
}

Swift: Adding gradient layer to button. Layer length error

let gradient: CAGradientLayer = CAGradientLayer()
let colorTop = UIColor(red: 112.0/255.0, green: 219.0/255.0, blue: 155.0/255.0, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 86.0/255.0, green: 197.0/255.0, blue: 238.0/255.0, alpha: 1.0).CGColor
gradient.colors = [colorTop, colorBottom]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.frame = loginButton.bounds
gradient.cornerRadius = 5
loginButton.layer.addSublayer(gradient)
The resulting gradient runs off goes beyond the button's frame. Why does this happen?
Probably you are setting gradient layer in viewDidLoad() or viewWillAppear(). At that time controller did not calculated views sizes. At time you add this sublayer button size was not calculated yet, so sublayer size is wrong. So you should fix next things:
First of all you should add gradient at viewDidAppear(), at this point all view's sizes are calculated.
Second, you should use layer.insertSublayer(layer, atIndex:index) instead of addSublayer(layer). Because in your case sublayer will hide buttons native layer (title, background...)
You should recalculate your sublayer size in viewDidLayoutSubviews(). Because when your button will change it's size (while rotating for example), sublayer will not change it's frame, so you should change it by yourself.
Add clipsToBounds and cornerRadius to loginbutton. That should fix the problem.
loginButton.clipsToBounds = true
loginButton.layer.cornerRadius = 5;
Is your Login Button's frame correct?It seems correct when I reproduce
let loginButton = UIButton(frame: CGRect(x: 10, y: 50, width: 300, height: 30))
self.view.addSubview(loginButton)
let gradient:CAGradientLayer = CAGradientLayer()
let colorTop = UIColor(red: 112.0/255.0, green: 219.0/255.0, blue: 155.0/255.0, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 86.0/255.0, green: 197.0/255.0, blue: 238.0/255.0, alpha: 1.0).CGColor
gradient.colors = [colorTop, colorBottom]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.frame = loginButton.bounds
gradient.cornerRadius = 5
loginButton.layer.addSublayer(gradient)
And it appear like below

CALayer or UIView in iOS Swift?

can anyone point me to a tutorial or sample code (or both!) that explains the correct way to add views and layers for iOS.
ideally in Swift not Obj C.
I have code that works when adding SKNodes by themselves, no problem, but if i add a gradient layer - i want that to be sky in the background, the Gradient covers everything else.
I've tried various forms of adding sublayers at index above, etc, but nothing seems to work. I think this is my basic understanding of CALayer and UIView. I can't find a good tutorial :(
any help appreciated.
cheers
Adam.
here is a sample.
the view fills with the gradient, which is great, but the button seems to be hidden underneath, despite trying to force it above the background layer.
import QuartzCore
class NightScene: SKScene, SKPhysicsContactDelegate {
let playButton = SKSpriteNode(imageNamed: "play")
let gradient = CAGradientLayer()
gradient.frame = view.bounds
let colorTop = UIColor(red: 0.0, green: 0.0, blue: 0.100, alpha: 1.0).CGColor
let colorMid = UIColor(red: 0.0, green: 0.0, blue: 0.450, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 0.0, green: 0.0, blue: 0.260, alpha: 1.0).CGColor
let arrayColors: Array <AnyObject> = [colorTop, colorMid, colorBottom]
gradient.colors = arrayColors
gradient.locations = [ 0.0, 0.4, 1.0]
self.view.layer.insertSublayer(gradient, atIndex:0)
let sceneLayer = CALayer()
sceneLayer.frame = view.bounds
self.view.layer.insertSublayer(sceneLayer, above: gradient)
self.playButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidX(self.frame)*2.5)
self.addChild(playButton)
}
Even though this question is over a year old I am going to provide an answer after countless hours of searching myself. I found numerous similar questions with no / vague responses.
What I come to find out is that nodes are not layer backed like gradients. This results in the gradient taking over the whole UI view. Nodes are not visible even with zLocation set. This is for SpriteKit based projects.
I stumbled across a library that you can use to create gradient background. This library basically converts a gradient into a SKSpriteNode. Gradient -> Texture -> Node
https://www.github.com/braindrizzlestudio/BDGradientNode
From the developers
We wrote BDGradientNode because gradients are a bit of a pain to set up on the fly in SpriteKit. UIViews are CALayer-backed and have access to CAGradientLayer, making them simple--fairly simple--to make. (Though sweep gradients can't be done.) SKNodes are NOT layer-backed. While you can jump through some hoops to make images, and so textures, from layers that can be assigned to an SKSpriteNode (which is what we first did when we just needed a simple gradient in SpriteKit) it's both cumbersome and inflexible.
Simple Linear Background
Once the library is added your Xcode project, you can use the following to create a linear gradient background:
let color1 = UIColor(red: 0/255, green: 118/255, blue: 162/255, alpha: 1.0)
let color2 = UIColor(red: 0/255, green: 85/255, blue: 116/255, alpha: 1.0)
let colors = [color1, color2]
let blending : Float = 1.0
let startPoint = CGPoint(x: 0.5, y: 1.0)
let endPoint = CGPoint(x: 0.5, y: 0.0)
let nodeSize = CGSize(width: self.frame.width, height: self.size.height)
let texture = SKTexture(imageNamed: "dummypixel")
let myGradientNode = BDGradientNode(linearGradientWithTexture: texture, colors: colors, locations: nil, startPoint: startPoint, endPoint: endPoint, blending: blending, keepTextureShape: false, size: nodeSize)
myGradientNode.zPosition = 0
myGradientNode.position = CGPointMake(self.size.width/2, self.size.height/2)
I found the tutorial here very helpful:
http://www.raywenderlich.com/75270/make-game-like-candy-crush-with-swift-tutorial-part-1
It contains layers and is in Swift. I also followed a Game of Life tutorial which used the zPosition of a node to help with layering, though they were not called layers and were not set up like your gradient:
https://www.makegameswith.us/gamernews/399/create-the-game-of-life-using-swift-and-spritekit
I found that even when I removed the gradient I could not view your button in its location, but we might just be working with differently sized devices. Is your sceneLayer empty? I didn't understand the relationship between your sceneLayer and your playButton.

Resources