CGRect not appearing with gradient sublayer - swift

CGRect not appearing at the same time as gradient sublayer, it's one or the other
Drawing only the gradient layer or only the rectangle works fine.
guard let ctx = UIGraphicsGetCurrentContext() else { fatalError() }
ctx.setFillColor(red: 1, green: 0.5, blue: 0.5, alpha: 1)
let segment1 = CGRect(x: 20, y: 110, width: 30, height: 10)
ctx.fill(segment1)
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.colors = [UIColor.init(displayP3Red: 0.29, green: 0.56, blue: 1.0, alpha: 1).cgColor, UIColor.init(displayP3Red: 0.23, green: 0.19, blue: 0.8, alpha: 1).cgColor]
layer.insertSublayer(gradient, at: 0)
I was expecting them both to appear in the correct order

Use: gradient.render(in: ctx) instead of layer.insertSublayer(gradient, at: 0 and draw segement1 after that: (Assuming you are doing this in a custom view class)
class customView: UIView {
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { fatalError() }
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.colors = [UIColor.init(displayP3Red: 0.29, green: 0.56, blue: 1.0, alpha: 1).cgColor, UIColor.init(displayP3Red: 0.23, green: 0.19, blue: 0.8, alpha: 1).cgColor]
gradient.render(in: ctx)
ctx.setFillColor(red: 1, green: 0.5, blue: 0.5, alpha: 1)
let segment1 = CGRect(x: 20, y: 110, width: 30, height: 10)
ctx.fill(segment1)
}
}
This way you aren't using the CGGraphicsContext in addition to the CALayer, you are just using the CGGraphicsContext because you layer gets rendered using the ctx

Related

How can I extract the uislider gradient color at the thumb position?

func gradientImage(size: CGSize, colorSet: [CGColor]) throws -> UIImage? {
let tgl = CAGradientLayer()
tgl.frame = CGRect.init(x:0, y:0, width:size.width, height: size.height)
tgl.cornerRadius = tgl.frame.height / 2
tgl.masksToBounds = false
tgl.colors = colorSet
tgl.startPoint = CGPoint.init(x:0.0, y:0.5)
tgl.endPoint = CGPoint.init(x:1.0, y:0.5)
UIGraphicsBeginImageContextWithOptions(size, tgl.isOpaque, 0.0);
guard let context = UIGraphicsGetCurrentContext() else { return nil }
tgl.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()?.resizableImage(withCapInsets:
UIEdgeInsets.init(top: 0, left: size.height, bottom: 0, right: size.height))
UIGraphicsEndImageContext()
return image
}
func setSliderGradient() {
let minTrackStartColor = UIColor(red:111/255, green: 111/255, blue: 111/255, alpha: 1.0)
let maxTrackColor = UIColor(red: 222/255, green: 222/255, blue: 222/255, alpha: 1.0)
do {
bottomNavBar.slider.setMinimumTrackImage(try bottomNavBar.gradientImage(
size: CGSize(width: bottomNavBar.slider.frame.width, height: 2),
colorSet: [minTrackStartColor.cgColor, maxTrackColor.cgColor]),
for: .normal)
bottomNavBar.slider.setMaximumTrackImage(try bottomNavBar.gradientImage(
size: CGSize(width: bottomNavBar.slider.frame.width, height: 2),
colorSet: [minTrackStartColor.cgColor, maxTrackColor.cgColor]),
for: .normal)
let thumb = UIView(frame: CGRect(x: 0, y: 0, width: 19, height: 10))
thumb.backgroundColor = UIColor(red: 222/255, green: 222/255, blue: 222/255, alpha: 1)
thumb.layer.cornerRadius = 5
bottomNavBar.slider.setThumbImage(thumb.asImage(), for: .normal)
} catch {
bottomNavBar.slider.minimumTrackTintColor = minTrackStartColor
bottomNavBar.slider.maximumTrackTintColor = maxTrackColor
}
}
In uislider, greadient is set as above code.
I want to color the thumb of the location according to the movement of the thumb.
How can I extract the uislider gradient color at the thumb position?
Try to create a gradient layer and update startPoint, endPoint and location depending on your current slider value.
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorStart.cgColor, colorEnd.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
gradientLayer.locations = [0, 1]
gradientLayer.frame = bounds

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 is my Gradient Layer smaller than the UITextField I am applying it to?

I am trying to give my text fields a gradient background. I am using the following code:
import UIKit
extension UITextField {
func gradientBackground(firstColor: UIColor, secondColor: UIColor){
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
gradientLayer.locations = [0.0, 1.0]
gradientLayer.startPoint = CGPoint(x:0.0, y:0.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
layer.addSublayer(gradientLayer)
}
}
class gradientTeLabel: UITextField {
override func didMoveToWindow() {
self.gradientBackground(firstColor: UIColor(red: 0.90, green: 0.61, blue: 0.00, alpha: 1), secondColor: UIColor(red: 0.70, green: 0.61, blue: 0.70, alpha: 1))
}
}
What I did was to create an extension and a class which I will attach to some UITextFields. The result is the gradient layer is a little bit shorter than the textfield and it kind of starts a few pixels higher inside the texfield instead of covering it all. What can I do?
Move code to layoutSubviews , As it contains the right bounds
class gradientTeLabel: UITextField {
var once = true
override func layoutSubviews() {
super.layoutSubviews()
if once {
self.gradientBackground(firstColor: UIColor(red: 0.90, green: 0.61, blue: 0.00, alpha: 1), secondColor: UIColor(red: 0.70, green: 0.61, blue: 0.70, alpha: 1))
once = false
}
}
}

How to change the color of the Mask View?

I am not sure if I understand the concept of Masking correctly but I am trying to recreate the Twitter logo expansion animation in their app:
Twitter Logo expansion
I have this code so far:
class LaunchScreenViewController: UIViewController {
var mask: CALayer!
override func viewDidLoad() {
setUpViewMask()
}
func setUpViewMask() {
mask = CALayer()
mask.contents = UIImage(named: "logo_mask")?.cgImage
mask.contentsGravity = kCAGravityResizeAspect
mask!.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
mask!.anchorPoint = CGPoint(x: 0.5, y: 0.5)
mask!.position = CGPoint(x: view.frame.size.width/2, y: view.frame.size.height/2)
view.layer.backgroundColor = UIColor(red: 70/255, green: 154/255, blue: 233/255, alpha: 1).cgColor
view.layer.mask = mask
}
}
The output of this is:
How would I change the black background to be blue? I tried doing but it didn't seem to work:
view.layer.backgroundColor = UIColor(red: 70/255, green: 154/255, blue: 233/255, alpha: 1).cgColor
Create an intermediate layer where you apply mask. Set the background of your view to the desired background, and set background color of the intermediate layer to the color that you wish your mask to appear in. Something like this,
view.backgroundColor = UIColor(red: 70/255, green: 154/255, blue: 233/255, alpha: 1) // set background of the view portion that do not include mask
let parentLayer = CALayer()
parentLayer.frame = view.bounds
parentLayer.backgroundColor = UIColor.white.cgColor // sets background of mask
view.layer.addSublayer(parentLayer)
let mask = CALayer()
mask.contents = UIImage(named: "twitter.png")?.cgImage
mask.contentsGravity = kCAGravityResizeAspect
mask.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
mask.anchorPoint = CGPoint(x: 0.5, y: 0.5)
mask.position = CGPoint(x: view.frame.size.width/2, y: view.frame.size.height/2)
parentLayer.mask = mask
This can be achieved by changing the background color of appDelegate's window...
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window!.backgroundColor = UIColor.blue

How do I use variables in a UIColor?

What type of variable should I be using for UIColor() and
Why won't this code work?
I am trying to using variables created in a different class to be the amounts for red, green, and blue. I did the variables the same for all the colors but get the error: 'extra argument green in call'
import UIKit
class Color: UIView
{
var colors = ViewController()
override func drawRect(rect: CGRect)
{
let swiftColor = UIColor(red: 1, green: 165/255, blue: 0, alpha: 1);
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 5.0)
CGContextSetStrokeColorWithColor(context,
UIColor(red: CGFloat(colors.red1), green: CGFloat(colors.green1), blue: CGFloat(colors.blue1), alpha: 1.0))
let rectangle = CGRectMake(60,170,200,80)
CGContextAddRect(context, rectangle)
CGContextStrokePath(context)
CGContextSetFillColorWithColor(context,
UIColor(red: CGFloat(colors.red1), green: CGFloat(colors.green1), blue: CGFloat(colors.blue1), alpha: 1.0))
CGContextFillRect(context, rectangle)
}
}
Try this.
class Color: UIView
{
var colors = ViewController()
override func drawRect(rect: CGRect)
{
let swiftColor = UIColor(red: 1, green: 165/255, blue: 0, alpha: 1);
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 5.0)
CGContextSetStrokeColorWithColor(context,
UIColor(red: CGFloat(colors.red1), green: CGFloat(colors.green1), blue: CGFloat(colors.blue1), alpha: 1.0).CGColor)
let rectangle = CGRectMake(60,170,200,80)
CGContextAddRect(context, rectangle)
CGContextStrokePath(context)
CGContextSetFillColorWithColor(context,
UIColor(red: CGFloat(colors.red1), green: CGFloat(colors.green1), blue: CGFloat(colors.blue1), alpha: 1.0).CGColor)
CGContextFillRect(context, rectangle)
}
}
CGContextSetStrokeColorWithColor expects a CGColor as parameter, but you are providing UIColor.