Rendering button with CAGradientLayer - swift

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".

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

how do i set the background color of UIViews to be a gradient color in 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
}
}

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
}
}

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?

Adding horizontal gradient to borderline

I created simple borderline into my view. However I am struggling giving horizontal gradient background color to it. How should I do it?
I tried like this but it just sets the color to white:
let border = CAGradientLayer()
border.frame = CGRect(x: 0, y: self.mainView.frame.height - 2, width: self.mainView.frame.width, height: 2)
border.backgroundColor = UIColor.gray.cgColor
let color1 = UIColor.black.withAlphaComponent(0.1).cgColor as CGColor
let color2 = UIColor.white.withAlphaComponent(0.9).cgColor as CGColor
border.locations = [0.60, 1.0]// Are these right coordinates?
border.colors = [color2, color1]
I got it working like this:
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 0, y: self.mainView.frame.height - 2, width: self.mainView.frame.width, height: 2)
gradientLayer.colors = [UIColor.green,UIColor.blue ].map{$0.cgColor}
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
Instead of using CALayer() I had to use CAGradientLayer()