how do i set the background color of UIViews to be a gradient color in swift? - swift

Im trying to set the color of my button and labels to a gradient color in swift with the following code:
extension UIView {
func setGradientColor(colorOne: UIColor, colorTwo: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [colorOne.cgColor, colorTwo.cgColor]
gradientLayer.locations = [0.0,0.1]
gradientLayer.startPoint = CGPoint(x: 1.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
layer.insertSublayer(gradientLayer, at: 0)
}
}
and then in the sign in form i use the extension like this:
let logo: UILabel = {
let logo = UILabel()
logo.text = "Logo"
logo.setGradientColor(colorOne: UIColor.blue, colorTwo: UIColor.yellow)
logo.textAlignment = .center
logo.font = UIFont.boldSystemFont(ofSize: 59)
return logo
}()
but it still shows up as black.
how do i fix this?

What you posted i review that ... call setGradietColor(colorOne: UIColor.blue, colorTwo: UIColor.yellow) after setting the frame or constraints to the logo view
You can add gradient layer in your view
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [UIColor.black.cgColor, UIColor.blue.cgColor]
gradient.locations = [0.0 , 1.0]
gradient.startPoint = CGPoint(x : 0.0, y : 0)
gradient.endPoint = CGPoint(x :0.0, y: 0.5) // you need to play with 0.15 to adjust gradient vertically
gradient.frame = view.bounds
view.layer.addSublayer(gradient)

You're facing this issue because you're not updating the frame of gradientLayer when bounds of logo updates. For example in ViewController you can give this code if you can have the reference to your gradientLayer.
class ViewController: UIViewController {
var gradient: CAGradientLayer?
let logo: UILabel = {
let logo = UILabel()
logo.text = "Logo"
gradient = logo.setGradietColor(colorOne: UIColor.blue, colorTwo: UIColor.yellow)
logo.textAlignment = .center
logo.font = UIFont.boldSystemFont(ofSize: 59)
return logo
}()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
gradient?.frame = logo.bounds
}
}
Try returning the layer from your method and modify your function like this:
extension UIView {
#discardableResult
func setGradietColor(colorOne: UIColor, colorTwo: UIColor) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [colorOne.cgColor, colorTwo.cgColor]
gradientLayer.locations = [0.0,0.1]
gradientLayer.startPoint = CGPoint(x: 1.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
layer.insertSublayer(gradientLayer, at: 0)
return layer
}
}

Related

How to put a gradient in a background button witch contains a system image?

I have a button with a system image:
#IBOutlet weak var ampouleButton: UIButton!
in the viewdid load, i put this:
let ampouleButtonConfig = UIImage.SymbolConfiguration(
pointSize: 30,
weight: .regular,
scale: .large)
let ampouleButtonImage = UIImage(
systemName: "lightbulb",
withConfiguration: ampouleButtonConfig)
ampouleButton.backgroundColor = Theme.gold03 // i need to put here a gradient
ampouleButton.setImage(ampouleButtonImage, for: .normal)
ampouleButton.tintColor = Theme.blanc
ampouleButton.layer.cornerRadius = ampouleButton.frame.height / 2
ampouleButton.layer.shadowOpacity = 0.4
ampouleButton.layer.shadowRadius = 3
ampouleButton.layer.shadowOffset =
CGSize(width: 0, height: 5)
ampouleButton.alpha = 1
instead of the background color, i need to put a gradient.
i tested this but it didn't work:
let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.ampouleButton.bounds
gradientLayer.colors = [UIColor.yellow.cgColor, UIColor.white.cgColor]
ampouleButton.layer.insertSublayer(gradientLayer, at: 0)
Actually, the button image goes behind the layer. Try this:
extension UIButton {
func applyGradient(colors: [CGColor], radius: CGFloat = 0, startGradient: CGPoint = .init(x: 0.5, y: 0), endGradient: CGPoint = .init(x: 0.5, y: 1)) {
// check first if there is already a gradient layer to avoid adding more than one
let gradientLayer = CAGradientLayer()
gradientLayer.cornerRadius = radius
gradientLayer.colors = colors
gradientLayer.startPoint = startGradient
gradientLayer.endPoint = endGradient
gradientLayer.frame = bounds
layer.insertSublayer(gradientLayer, at: 0)
}
}
And in the viewDidLoad put:
ampouleButton.applyGradient(colors: [Theme.bleu!.cgColor, Theme.softBlue!.cgColor], radius: self.ampouleButton.frame.height / 2, startGradient: CGPoint(x: 0, y: 0.5), endGradient: CGPoint(x: 1, y: 0))
if let imgView = ampouleButton.imageView { ampouleButton.bringSubviewToFront(imgView) }
Find applyGradient function from here : https://stackoverflow.com/a/62093932/2303865

Swift make UIView border into Gradient Color

I want to create a gradient border on a UIView.
The following code can produce a solid for the view Box1.
nothing I have found allows me to change the frameColor to a gradient.
var frameColor = UIColor.red.cgColor
var leftBorder = CALayer()
leftBorder.frame = CGRect(x: 0.0, y: 0, width: 1, height: box1.frame.size.height )
leftBorder.backgroundColor = frameColor
I am using Swift 5 and Xcode 11.
Thank you.
Try with below extension
public extension UIView {
private static let kLayerNameGradientBorder = "GradientBorderLayer"
func setGradientBorder(
width: CGFloat,
colors: [UIColor],
startPoint: CGPoint = CGPoint(x: 0.5, y: 0),
endPoint: CGPoint = CGPoint(x: 0.5, y: 1)
) {
let existedBorder = gradientBorderLayer()
let border = existedBorder ?? CAGradientLayer()
border.frame = bounds
border.colors = colors.map { return $0.cgColor }
border.startPoint = startPoint
border.endPoint = endPoint
let mask = CAShapeLayer()
mask.path = UIBezierPath(roundedRect: bounds, cornerRadius: 0).cgPath
mask.fillColor = UIColor.clear.cgColor
mask.strokeColor = UIColor.white.cgColor
mask.lineWidth = width
border.mask = mask
let exists = existedBorder != nil
if !exists {
layer.addSublayer(border)
}
}
func removeGradientBorder() {
self.gradientBorderLayer()?.removeFromSuperlayer()
}
private func gradientBorderLayer() -> CAGradientLayer? {
let borderLayers = layer.sublayers?.filter { return $0.name == UIView.kLayerNameGradientBorder }
if borderLayers?.count ?? 0 > 1 {
fatalError()
}
return borderLayers?.first as? CAGradientLayer
}
}
Usage
self.borderView.setGradientBorder(width: 5.0, colors: [UIColor.red , UIColor.blue])
I hope this will reach your requirement.
https://medium.com/#kushal0409/gradient-button-3dc8ef763039
There is no off-the-shelf way to do this, but you could build it yourself.
Off the top of my head, the approach might look like this:
Create a CAGradientLayer and set it up to draw your gradient as
desired.
Create a CAShapeLayer that contains an empty rectangle that is your
frame.
Add your shape layer as the mask of your gradient layer.
Add the gradient layer to your view as a sub-layer of the view's
content layer.
Swift 5 extension (works with corner radius)
extension UIView {
func gradientBorder(colors: [UIColor], isVertical: Bool){
self.layer.masksToBounds = true
//Create gradient layer
let gradient = CAGradientLayer()
gradient.frame = CGRect(origin: CGPoint.zero, size: self.bounds.size)
gradient.colors = colors.map({ (color) -> CGColor in
color.cgColor
})
//Set gradient direction
if(isVertical){
gradient.startPoint = CGPoint(x: 0.5, y: 0)
gradient.endPoint = CGPoint(x: 0.5, y: 1)
}
else {
gradient.startPoint = CGPoint(x: 0, y: 0.5)
gradient.endPoint = CGPoint(x: 1, y: 0.5)
}
//Create shape layer
let shape = CAShapeLayer()
shape.lineWidth = 1
shape.path = UIBezierPath(roundedRect: gradient.frame.insetBy(dx: 1, dy: 1), cornerRadius: self.layer.cornerRadius).cgPath
shape.strokeColor = UIColor.black.cgColor
shape.fillColor = UIColor.clear.cgColor
gradient.mask = shape
//Add layer to view
self.layer.addSublayer(gradient)
gradient.zPosition = 0
}
}

Issue in applying gradient color on view and button in swift

i'm trying to apply gradient color on view and button, but i'm facing an issue that it is not applying on the entire frame of button and view as you can see in screenshot.I have used this code and giving my custom hex values for color,
func applyGradient(colours: [UIColor]) -> Void {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = colours.map { $0.cgColor }
gradient.startPoint = CGPoint(x : 0.0, y : 0.5)
gradient.endPoint = CGPoint(x :1.0, y: 1.5)
self.layer.insertSublayer(gradient, at: 0)
}
and applying like this by calling this function,
self.headerView.applyGradient(colours: [UIColor.init(hexString: "54F3FF"),UIColor.init(hexString: "43D7FF") ,UIColor.init(hexString: "30B7FF")])
Now when i run the app and test it, it looks like this
How can i apply gradient to full frame of view and button? What is the mistake in my code?
Try this
override func viewDidLayoutSubviews() {
self.headerView.applyGradient(colours: [UIColor.init(hexString: "54F3FF"),UIColor.init(hexString: "43D7FF") ,UIColor.init(hexString: "30B7FF")])
}
Hope this helps
#Junaid Khan,
Try like below,
extension UIView {
func applyGradient(colours: [CGColor], startPoint: CGPoint, endPoint: CGPoint, frame: CGRect) -> Void {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = colours
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
gradientLayer.frame = frame
layer.insertSublayer(gradientLayer, at: 0)
}
}
If you have using constraints then call like below on your constraints method,
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
yourView?.applyGradient(colours: [UIColor.red.cgColor, UIColor.yellow.cgColor], startPoint: CGPoint(x: 0, y: 1), endPoint: CGPoint(x: 1, y: 1), frame: (yourView?.bounds)!)
}
Hope it's save your time!
Note: You can convert or get RGB colours by using your hexa color value.

Swift macOS label Gradient Text

I have a label in a macOS project which when connected becomes an NSTextField. I want to make the text have a gradient overlay.
I have some code to do this with an iOS UIButton, but for this project I keep getting the error that NSView has no such thing called mask and I don't know what to mask it to
extension NSTextField {
func applyGradientText(colors: [CGColor]) {
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.colors = colors
layer?.insertSublayer(gradient, at: 0)
let overlayView = NSView(frame: bounds)
overlayView.layer?.insertSublayer(gradient, at: 0)
overlayView has nothing called mask, and I don't know what to mask to
overlayView.mask = SOMETHING
addSubview(overlayView)
}
}
You need to call wantsLayer = true on the NSTextField as it doesn't have a layer by default. Then just set layer?.mask = gradient and the label will show where gradient is CGColor.clear.
label.applyGradientText(colors: [CGColor.black, CGColor.clear])
extension NSTextField {
func applyGradientText(colors: [CGColor]) {
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.colors = colors
wantsLayer = true
layer?.mask = gradient
}
}
Does this do what you want?

Rendering button with CAGradientLayer

when I set a button with the CAGradientLayer it is not displayed correctly.
func setGradientBackground(color_A: UIColor, color_B: UIColor, indexLayer : Int){
let granderLayer = CAGradientLayer()
granderLayer.frame = bounds
granderLayer.colors = [color_A.cgColor, color_B.cgColor]
granderLayer.locations = [0.0, 1.0]
granderLayer.startPoint = CGPoint(x: 1.0, y: 1.0)
granderLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
layer.insertSublayer(granderLayer, at: UInt32(indexLayer))
}
in the case of a UITableView after a scroll this works
You should check the value of bounds in this line: "granderLayer.frame = bounds".