Swift - Working With Gradients - swift

I have encountered a problem involving setting gradients for labels and buttons. I know this question has been asked a lot, but no answer has seemed to solve my problem. Here is the screen as I want it to look:
This is my code:
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var logoLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
loginButton.backgroundColor = UIColor.clear
let loginButtonGradient = createBlueGreenGradient(from: loginButton.bounds)
self.view.layer.insertSublayer(loginButtonGradient, at: 0)
signUpButton.backgroundColor = UIColor.clear
let signUpButtonGradient = createBlueGreenGradient(from: signUpButton.bounds)
self.view.layer.insertSublayer(signUpButtonGradient, at: 0)
logoLabel.backgroundColor = UIColor.clear
let logoLabelGradient = createBlueGreenGradient(from: logoLabel.bounds)
self.view.layer.insertSublayer(logoLabelGradient, at: 0)
loginButton.layer.cornerRadius = 100
signUpButton.layer.cornerRadius = 100
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func createBlueGreenGradient(from bounds: CGRect) -> CAGradientLayer{
let topColor = UIColor(red: 84/255, green: 183/255, blue: 211/255, alpha: 1)
let bottomColor = UIColor(red: 119/255, green: 202/255, blue: 151/255, alpha: 1)
let gradientColors: [UIColor] = [topColor, bottomColor]
let gradientLocations: [NSNumber] = [0.0, 1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
gradientLayer.frame = bounds
return gradientLayer
}
And this is the wrong result:
Somebody please help me. I'm not sure what I'm doing wrong.

There are lots of issue with your code.
Divide the color with Float number instead of Int means it should be 255.0 not 255.
Now for colors property of CAGradientLayer you need to set array of CGColor not array of UIColor.
Also set startPoint and endPoint property of CAGradientLayer to make horizontal gradient color.
Currently you are adding this GradientLayer in your self.view instead of its specific button.
Set the cornerRadius of your button on basis of its height not with some constant 100 also after setting cornerRadius you need to also set masksToBounds property of layer to true.
Now for your logo label, you cannot set textColor as Gradient color directly what you need to do is draw the desired gradient on a UIImage and then use that UIImage to set the color pattern for your Label check this SO reference for that.
After making all this changes your code should be like.
func createBlueGreenGradient(from bounds: CGRect) -> CAGradientLayer{
let topColor = UIColor(red: 84/255.0, green: 183/255.0, blue: 211/255.0, alpha: 1).cgColor
let bottomColor = UIColor(red: 119/255.0, green: 202/255.0, blue: 151/255.0, alpha: 1).cgColor
let gradientColors = [topColor, bottomColor]
let gradientLocations: [NSNumber] = [0.0, 1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
//Set startPoint and endPoint property also
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
gradientLayer.frame = bounds
return gradientLayer
}
Now set gradientLayer in viewDidLoad this way.
override func viewDidLoad() {
super.viewDidLoad()
let loginButtonGradient = createBlueGreenGradient(from: loginButton.bounds)
self.loginButton.layer.insertSublayer(loginButtonGradient, at: 0)
let signUpButtonGradient = createBlueGreenGradient(from: signUpButton.bounds)
self.signUpButton.layer.insertSublayer(signUpButtonGradient, at: 0)
loginButton.layer.cornerRadius = loginButton.frame.size.height / 2
loginButton.layer.masksToBounds = true
signUpButton.layer.cornerRadius = signUpButton.frame.size.height / 2
signUpButton.layer.masksToBounds = true
}

Your method like this:
func createBlueGreenGradient(from bounds: CGRect) -> CAGradientLayer{
let topColor = UIColor(red: 84/255, green: 183/255, blue: 211/255, alpha: 1).cgColor
let bottomColor = UIColor(red: 119/255, green: 202/255, blue: 151/255, alpha: 1).cgColor
let gradientColors = [topColor, bottomColor]
let gradientLocations: [NSNumber] = [0.0, 1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
gradientLayer.frame = bounds
return gradientLayer
}

Oh my goodness I had the same problem, but played around with it. This is caused because you didnt add .cgcolor. For example :
let topColor = UIColor(red: 84/255, green: 183/255, blue: 211/255, alpha: 1).cgColor
let bottomColor = UIColor(red: 119/255, green: 202/255, blue: 151/255, alpha: 1).cgColor
let gradientColors = [topColor, bottomColor]
Let me know if it works.

Related

Problem with gradient on the background of a table swift

I have a tableview with the cells and I want apply a custom gradient. I've searched here but nothing works with my code.
My part of the code where I try to add the gradient
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Menú Principal"
tableView.backgroundView?.aplicarDegradadoDeportes()
self.navigationItem.setHidesBackButton(true, animated: true)
}
This is my function for the gradient
func aplicarDegradadoDeportes() {
let colorInicio = UIColor(red: 255/255, green: 59/255, blue: 0/255, alpha: 1.0).cgColor
let colorFin = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0).cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorInicio, colorFin]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.frame = self.bounds
self.layer.insertSublayer(gradientLayer, at:0)
}
Please help
You could create a custom UITableViewCell subclass and override the layoutSubviews() function.
For example like this:
class GradientTableViewCell: UITableViewCell {
// Property to store the gradient layer
private var gradientLayer: CAGradientLayer?
override func layoutSubviews() {
super.layoutSubviews()
// Check if gradient layer already exists
if gradientLayer == nil {
// Set the colors for the gradient
let colorInicio = UIColor(red: 255/255, green: 59/255, blue: 0/255, alpha: 1.0).cgColor
let colorFin = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0).cgColor
// Create the gradient layer and set its properties
gradientLayer = CAGradientLayer()
gradientLayer?.colors = [colorInicio, colorFin]
gradientLayer?.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer?.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer?.frame = self.bounds
// Add the gradient layer as a sublayer to the cell's content view
self.contentView.layer.insertSublayer(gradientLayer!, at:0)
}
}
}
In your controller you need the set the cell class to GradientTableViewCell:
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Menú Principal"
self.navigationItem.setHidesBackButton(true, animated: true)
// Set the cell class for the table view to be GradientTableViewCell
self.tableView.register(GradientTableViewCell.self, forCellReuseIdentifier: "Cell")
}
In the cellForRowAt function of your table data dequeue a GradientTableViewCell instead of UITableViewCell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Dequeue a GradientTableViewCell instead of a UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! GradientTableViewCell
// Configure the cell as needed
return cell
}
Now you should be able to set the gradient to the background of the cells
The backgroundView property of UITableView is nil by default. So your aplicarDegradadoDeportes function is never actually called.
Set a view as the backgroundView then it should work.
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Menú Principal"
let background = UIView()
tableView.backgroundView = background
background.aplicarDegradadoDeportes()
self.navigationItem.setHidesBackButton(true, animated: true)
}
The only issue is that the tableView will update the size of backgroundView as needed but your additional layer may not automatically get resized to match.
One solution is to move the code to setup the background view in viewWillAppear or you can override viewDidLayoutSubviews and update the layer's frame.
The best solution is to create a custom UIView subclass that draws the gradient so it stays up to date as it is sized.
class GradientView: UIView {
var gradient: CALayer!
override func didMoveToSuperview() {
super.didMoveToSuperview()
if superview != nil {
let colorInicio = UIColor(red: 255/255, green: 59/255, blue: 0/255, alpha: 1.0).cgColor
let colorFin = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0).cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorInicio, colorFin]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.frame = self.bounds
self.layer.insertSublayer(gradientLayer, at:0)
gradient = gradientLayer
}
}
override var frame: CGRect {
didSet {
gradient?.frame = bounds
}
}
}
Then your view controller viewDidLoad becomes:
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Menú Principal"
let background = GradientView()
tableView.backgroundView = background
self.navigationItem.setHidesBackButton(true, animated: true)
}

How to fix: gradient background at landscaping?

I have this code which creates a gradient background.
When I rotate the deviace to landscape mode, the gradient background doesnt fill up to the whole size of the screen, some parts are white.
My goal is the whenever the orrientation changes, the gradient should fill the whole screen.
let gradient: CAGradientLayer = CAGradientLayer()
let color1 = UIColor(red: 198.0/255.0 , green: 255.0/255.0, blue: 221.0/255.0, alpha: 1.0).cgColor
let color2 = UIColor(red: 251.0/255.0, green: 215.0/255.0, blue: 134.0/255.0, alpha: 1.0).cgColor
let color3 = UIColor(red: 247.0/255.0, green: 121.0/255.0, blue: 125.0/255.0, alpha: 1.0).cgColor
gradient.name="asd"
gradient.colors = [color1,color2,color3]
gradient.locations = [0.0 , 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
gradient.frame = CGRect(x: 0.0, y: 0.0, width: wid, height: heu)
self.view.layer.insertSublayer(gradient, at: 0)
}
Hold the gradient layer as a property and update its frame in layoutSubview()
var gradientLayer: CAGradientLayer?
override func viewDidLoad() {
super.viewDidLoad()
///
/// YOUR CODE
///
gradientLayer = gradient
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer?.frame = self.view.bounds
}

Why are UIViews background color is not updating?

Switch statement works but won't reset view background colours etc.
I have a UIImage (icon) and a UIButton embedded within a UIView (of custom type DropShadowCircleView) as per image below.
When the walking button is tapped a var navigationOption is set to either walking or driving and setupNavigationSelectionView() is executed.
Problem is: case "walking" of the switch works perfectly, but case "driving" doesn't reset the UIView and icon tint color witcback to their original setting eg; background color etc.. any ideas why?
func setupNavigationSelectionView(){
switch navigationOption {
case "walking":
walkingBg.setGradientBackground(colourOne: softGreen, ColourTwo: softBlue)
walkingBg.layer.cornerRadius = walkingBg.frame.width / 2
walkingBg.clipsToBounds = true
walkingIcon.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
case "driving":
walkingBg.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
walkingBg.layer.cornerRadius = walkingBg.frame.width / 2
walkingBg.clipsToBounds = true
walkingIcon.tintColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
default:
break
}
}
EDIT: this is my DropShadowCircleView class
class DropShadowCircleView: UIView {
override func awakeFromNib() {
setupView()
super.awakeFromNib()
}
func setupView(){
self.layer.shadowOpacity = 0.50
self.layer.shadowRadius = 20
self.layer.shadowColor = UIColor.black.cgColor
self.layer.cornerRadius = self.frame.width / 2
}
}
EDIT: This is my setGradientBackground function which is within an extension file to UIView
func setGradientBackground(colourOne: UIColor, ColourTwo: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [colourOne.cgColor, ColourTwo.cgColor]
gradientLayer.locations = [0.0, 1.0]
gradientLayer.startPoint = CGPoint(x: 1.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
layer.insertSublayer(gradientLayer, at: 0)
}
You need to remove your gradient layer when you reset your icon.
Add this to your extension UIView:
func removeGradientBackground() {
guard
let idx = layer.sublayers?.index(where: { $0 is CAGradientLayer })
else { return }
layer.sublayers?.remove(at: idx)
}
and call it when you are resetting your icon.

Gradient color effect on UIView in iOS 10 Swift 2.3 Xcode 8

I am trying to achieve a gradient color on a UIView or button with two color black which fades out to clear color or white color (please see image).
I have tried using different combinations of white color, clear color; experimenting with alpha as well. I have also set the locations property as can be seen in below code but I am not able to achieve desired results.
Can anyone tell me where I am wrong. :)
let colorClear = UIColor.clearColor().CGColor
let colorLeft = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.9).CGColor
let colorRight = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).CGColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorLeft, colorRight]
gradientLayer.locations = [ 0.1, 0.9]
gradientLayer.frame = self.createAccountView.bounds
gradientLayer.startPoint = CGPoint(x:0.0, y:0.5)
gradientLayer.endPoint = CGPoint(x:1.0, y:0.5)
createAccountView.layer.addSublayer(gradientLayer)
createAccountView.layer.masksToBounds = true
The desired result is the one in which black color transitions to a faded one.
I have already tried setting both colors as black and the color1 with an alpha.
I have already tried commenting locations property.
you should set gradientLayer.frame in viewDidLayoutSubviews().
Like this:
class ViewController: UIViewController {
let gradientLayer = CAGradientLayer()
override func viewDidLoad() {
let colorClear = UIColor.clearColor().CGColor
let colorLeft = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.9).CGColor
let colorRight = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).CGColor
self.gradientLayer.colors = [colorLeft, colorRight]
self.gradientLayer.locations = [ 0.1, 0.9]
self.gradientLayer.startPoint = CGPoint(x:0.0, y:0.5)
self.gradientLayer.endPoint = CGPoint(x:1.0, y:0.5)
createAccountView.layer.addSublayer(self.gradientLayer)
createAccountView.layer.masksToBounds = true
}
override viewDidLayoutSubviews() {
super.viewDidLayoutSubViews()
self.gradientLayer.frame = self.createAccountView.bounds
}

CAGradientLayerHides my UILabel text

I am trying to add gradient background to my labels (which are connected from UserInterface) , but it hides label's text.
This is my code so far:
//MARK: Grdient label func
func gradientBackground(label:UILabel){
let four = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1).CGColor
let three = UIColor.whiteColor().CGColor
let two = UIColor.whiteColor().CGColor
let one = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1).CGColor
let gradient = CAGradientLayer()
gradient.locations = [0.0,0.2,0.8,1.0]
gradient.colors = [one,two,three,four]
gradient.startPoint = CGPointMake(0.0, 0.5)
gradient.endPoint = CGPointMake(1.0, 0.5)
gradient.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, label.bounds.height)
let backView = UIView()
backView.frame = CGRectMake(0, 0, label.bounds.width, label.bounds.height)
backView.backgroundColor = UIColor.clearColor()
backView.layer.insertSublayer(gradient, atIndex: 0)
label.insertSubview(backView, atIndex: 0)
label.backgroundColor = UIColor.clearColor()
label.textColor = UIColor.blackColor()
label.tintColor = UIColor.blackColor()
}
Then I use the function like this:
override func viewDidLoad() {
super.viewDidLoad()
//MARK: Gradient background
gradientBackground(firstLabel)
}
My question is, what is wrong?
Thank you.
check if it is your label "firstLabel" visible
check if your func draw img under the text