Issue with applying gradient on imageview of Tableview - uitableview

Gradient effect is being applied but not exactly on the image
Below is my code:
let gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: reportCell.reportImageView.bounds.size.width, height: reportCell.reportImageView.bounds.size.height)
gradient.colors = [UIColor.clear.cgColor,UIColor.black.cgColor]
gradient.locations = [0.0, 1.0]
reportCell.reportImageView.layer.addSublayer(gradient)
reportCell.reportImageView.image = UIImage(named: "\(indexPath.row).jpeg")

Related

How do you design a gradient for a layer in iOS?

I have to follow through my designer's gradient layer as shown below and I'm running into a wall trying to replicate her design (below).
I have the following code to try to replicate the same shadow but it is too solid compared to her gradient. How do I reduce my layer to have a gradient look and feel?
backgroundView.layer.shadowColor = UIColor.Custom.darkBlue.cgColor
backgroundView.layer.shadowOpacity = 1.0
backgroundView.layer.shadowRadius = 10
EDIT:
I implemented what I needed using #Frankenstein's solution below.
backgroundView.backgroundColor = UIColor.Custom.darkBlue
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [UIColor.black.cgColor, UIColor.Custom.darkBlue.cgColor]
gradient.frame = CGRect(x: backgroundView.frame.origin.x, y: backgroundView.frame.origin.y - 39, width: view.bounds.width, height: 40)
view.layer.addSublayer(gradient)
With the expected result below. Thank you!
You need to add a new CAGradientLayer and not set the shadow, here is an example:
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [UIColor.black.cgColor, UIColor.Custom.darkBlue.cgColor]
gradient.locations = [0.0 , 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 1.0)
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
gradient.frame = view.bounds
view.layer.addSublayer(gradient)
Here is how you can achieve that
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.15) // you need to play with 0.15 to adjust gradient vertically
gradient.frame = view.bounds
view.layer.addSublayer(gradient)
With 0.15 to 0.5 you get

Gradient over UIImageView

I've been trying to fill an image view with a gradient layer, but I can't seem to make it work, I tried to create CAGradientLayer, applied 2 colors on it then applied it as a mask to the main image layer.
let gradient = CAGradientLayer()
gradient.frame = (self.imageView?.bounds)!
gradient.colors = [UIColor.blue.cgColor, UIColor.purple.cgColor]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
gradient.locations = [0, 1]
self.imageView?.layer.mask = gradient
This is what I have, and this is what I want as a result:
UPDATE:
Found the solution here.
You can do something like this:
var gradient = CAGradientLayer()
gradient.frame = imageView.bounds
gradient.colors = [UIColor.blue.cgColor, UIColor.purple.cgColor]
imageView.layer.insertSublayer(gradient, at: 0)
I got this answer. Add extension of UIImage and just pass colours list to apply gradient.
import UIKit
extension UIImage {
func tintedWithLinearGradientColors(colorsArr: [CGColor]) -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
guard let context = UIGraphicsGetCurrentContext() else {
return UIImage()
}
context.translateBy(x: 0, y: self.size.height)
context.scaleBy(x: 1, y: -1)
context.setBlendMode(.normal)
let rect = CGRect.init(x: 0, y: 0, width: size.width, height: size.height)
// Create gradient
let colors = colorsArr as CFArray
let space = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: space, colors: colors, locations: nil)
// Apply gradient
context.clip(to: rect, mask: self.cgImage!)
context.drawLinearGradient(gradient!, start: CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: self.size.height), options: .drawsAfterEndLocation)
let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return gradientImage!
}
}

How to make a UIView have an effect of transparent gradient?

I want to make a UIView have an effect of transparent gradient from the middle to the left and right. Like in this example:
The word 籍 has the desired effect. This view is achieved by the class MarqueeLabel. I examined the source code, it is likely implemented by class CALayer.
In Swift 4: for top to bottom transparent gradient.
let gradient = CAGradientLayer()
gradient.startPoint = CGPoint(x: 0.5, y: 0.0)
gradient.endPoint = CGPoint(x: 0.5, y: 0.6)
let whiteColor = UIColor.white
gradient.colors = [whiteColor.withAlphaComponent(0.0).cgColor, whiteColor.withAlphaComponent(1.0).cgColor, whiteColor.withAlphaComponent(1.0).cgColor]
gradient.locations = [NSNumber(value: 0.0),NSNumber(value: 0.2),NSNumber(value: 1.0)]
gradient.frame = gradientView.bounds
gradientView.layer.mask = gradient
Screenshot
Swift code
let mask = CAGradientLayer()
mask.startPoint = CGPointMake(0.0, 0.5)
mask.endPoint = CGPointMake(1.0, 0.5)
let whiteColor = UIColor.whiteColor()
mask.colors = [whiteColor.colorWithAlphaComponent(0.0).CGColor,whiteColor.colorWithAlphaComponent(1.0),whiteColor.colorWithAlphaComponent(1.0).CGColor]
mask.locations = [NSNumber(double: 0.0),NSNumber(double: 0.2),NSNumber(double: 1.0)]
mask.frame = label.bounds
label.layer.mask = mask
You can use CAGradientLayer as following.
gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = baseView.bounds;
gradientLayer.startPoint = CGPointMake(0.5,0.0);
gradientLayer.endPoint = CGPointMake(0.5,1.0);
gradientLayer.locations = #[#(0.0), #(0.2), #(1.0)];
gradientLayer.colors = #[(id)[UIColor colorWithWhite:1.0 alpha:0.9].CGColor,
(id)[UIColor colorWithWhite:1.0 alpha:0.3].CGColor,
(id)[UIColor colorWithWhite:1.0 alpha:0.0].CGColor];
[baseView.layer addSublayer:gradientLayer];
CAGradientLayer supports several properties to make natural gradient, such as setting gradient direction by startPoint and endPoint, changing color curve by locations and colors.
You also make a transparent effect by using alpha channel of color.
Swift 3:
let mask = CAGradientLayer()
mask.startPoint = CGPoint(x: 0, y: 0.5)
mask.endPoint = CGPoint(x:1.0, y:0.5)
let whiteColor = UIColor.white
mask.colors = [whiteColor.withAlphaComponent(0.0).cgColor,whiteColor.withAlphaComponent(1.0),whiteColor.withAlphaComponent(1.0).cgColor]
mask.locations = [NSNumber(value: 0.0),NSNumber(value: 0.2),NSNumber(value: 1.0)]
mask.frame = view.bounds
view.layer.mask = mask
Use clear color instead of set the alpha value.
let gradientLayer = CAGradientLayer()
gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
gradientLayer.colors = [UIColor.clear.cgColor, UIColor.white.cgColor, UIColor.white.cgColor]
gradientLayer.locations = [0, 0.2, 1]
gradientLayer.frame = gradientView.bounds
gradientView.layer.mask = gradientLayer

How to give "locations" to CAGradientLayer

I have created CAGradientLayer having three colors, i need to give each color different locations.
Example:
Red = 0 to 50 %
Yellow = 51 to 80 %
Green = 81 to 100 %
I have tried with giving startPoint and endPoint but it did not work.
If you put the following code into a Playground you will get the exact desired output:
let view = UIView(frame: CGRectMake(0,0,200,100))
let layer = CAGradientLayer()
layer.frame = view.frame
layer.colors = [UIColor.greenColor().CGColor, UIColor.yellowColor().CGColor, UIColor.redColor().CGColor]
layer.locations = [0.0, 0.8, 1.0]
view.layer.addSublayer(layer)
XCPShowView("ident", view: view)
Outputting:
You simply define the colors as an array of CGColors, and an array of the same size of NSNumbers each between 0.0 and 1.0.
Dont use startPoint and endPoint for that - they are for defining from where to where the gradient is shown in the layer - it does not have anything to do with the percents and the colors etc.
More recent Swift3 version of the code:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
let layer = CAGradientLayer()
layer.frame = view.frame
layer.colors = [UIColor.green.cgColor, UIColor.yellow.cgColor, UIColor.red.cgColor]
layer.locations = [0.0, 0.8, 1.0]
view.layer.addSublayer(layer)
PlaygroundPage.current.liveView = view

How can I create a horizontal gradient background for my iOS nav bar?

I know how to set a navigation bar background color (with barTintColor), but now I am working on an iOS app that calls for a horizontal gradient (not the typical vertical gradient).
How can I create a navigation bar with a horizontal gradient background?
If you want to programmatically set the gradient of a given UINavigationBar I have a solution for you.
First setup a CAGradientLayer with your desired colors and locations.
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = navigationBar.bounds;
gradientLayer.colors = #[ (__bridge id)[UIColor greenColor].CGColor,
(__bridge id)[UIColor blueColor].CGColor ];
gradientLayer.startPoint = CGPointMake(0.0, 0.5);
gradientLayer.endPoint = CGPointMake(1.0, 0.5);
Then grab the UImage for that layer.
UIGraphicsBeginImageContext(gradientLayer.bounds.size);
[gradientLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Set the gradientImage as the backgroundImage for your UINavigationBar.
[navigationBar setBackgroundImage:gradientImage forBarMetrics:UIBarMetricsDefault];
Swift Solution:
[![// Setup the gradient
let gradientLayer = CAGradientLayer()
gradientLayer.frame = navigationBar.bounds
gradientLayer.colors = [UIColor.green.cgColor, UIColor.blue.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
// Render the gradient to UIImage
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Set the UIImage as background property
navigationBar.setBackgroundImage(image, for: UIBarMetrics.default)
Updated #JulianM answer for iOS 10 / swift 3.0:
let gradientLayer = CAGradientLayer()
var updatedFrame = self.navigationController!.navigationBar.bounds
updatedFrame.size.height += 20
gradientLayer.frame = updatedFrame
gradientLayer.colors = [UIColor.green.cgColor, UIColor.blue.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.navigationController!.navigationBar.setBackgroundImage(image, for: UIBarMetrics.default)
Swift
Add this function in global class
func setHorizontalGradientColor(view: UIView) {
let gradientLayer = CAGradientLayer()
var updatedFrame = view.bounds
updatedFrame.size.height += 20
gradientLayer.frame = updatedFrame
gradientLayer.colors = [UIColor.black.cgColor, UIColor.blue.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
view.layer.insertSublayer(gradientLayer, at: 0)
}
Use in anywhere:
setHorizontalGradientColor(view: self.bgView)
You can use that :
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"gardientImage"] forBarMetrics:UIBarMetricsDefault];
for ios 7 navigation bar height is 64px

Resources