How to set Gradient Background on UITable View Controller?
If I implent the above code, the gradient colours works well but I can't able to view the UIImage view, UIButton in the screen.. I can only able to see the gradient colour.. please help...
import UIKit
class HomeTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground()
}
//Mark:- Gradiant background colour
func setGradientBackground() {
let topColor = UIColor(red: 19/255, green: 163/255, blue: 203/255, alpha: 1)
let bottomColor = UIColor(red: 131/255, green: 197/255, blue: 86/255, alpha: 1)
let gradientColors: [CGColor] = [topColor.cgColor, bottomColor.cgColor]
let gradientLocations: [Float] = [0.0, 0.5]
let gradientLayer: CAGradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations as [NSNumber]?
gradientLayer.frame = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, at: 0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Try setting the backgroundView of the tableView. Initialize an Uiview your gradient view, set it's bound equal to tableView, do all necessary stuff to setup your gradient, set this UIview as your tableView's background view.
Related
I'm working on an iOS project that's creating all its UIs programmatically. Not storyboards.
I want to add a gradient to the background of a UIViewController's UIView.
I created the following extension method.
extension UIView {
func addGradient(colors: [UIColor]) {
let gradientLayer = CAGradientLayer()
gradientLayer.bounds = bounds
gradientLayer.colors = colors.map { $0.cgColor }
layer.insertSublayer(gradientLayer, at: 0)
}
}
And I added the gradient in the viewDidLoad of the ViewController like so.
let topColor = UIColor(red: 0.28, green: 0.521, blue: 0.696, alpha: 1)
let bottomColor = UIColor(red: 0.575, green: 0.615, blue: 0.692, alpha: 1)
view.addGradient(colors: [topColor, bottomColor])
But the gradient is not being applied to the full width and height of the screen.
I printed out the bounds of the view and it shows these values.
(0.0, 0.0, 375.0, 812.0)
So I'm not sure why the gradient is still not covering the full view.
In addGradient(colors:) method set the gradientLayer's frame instead of bounds, i.e.
func addGradient(colors: [UIColor]) {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds //here.....
//rest of the code...
}
Also, as suggested move your code to viewDidLayoutSubviews() method,
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let topColor = UIColor(red: 0.28, green: 0.521, blue: 0.696, alpha: 1)
let bottomColor = UIColor(red: 0.575, green: 0.615, blue: 0.692, alpha: 1)
view.addGradient(colors: [topColor, bottomColor])
}
This is because, the gradient's frame must change everytime there are any changes in the view's layout. Example, in portrait and landscape orientations.
When we are adding view bounds to Gradient layer frame that time we have to update frame in viewDidLayoutSubviews. It works fine for me
Following worked for me
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.gradient.frame = containerView.bounds
}
containerView is the view where i am setting gradient layer.
I try to make a standard gradient top-bottom with long UIView. But it's not full. The nib is part of UITableViewCell, so I don't have access to viewDidLayoutSubviews() as in this thread.
I've tried to call contentView.layoutIfNeeded() from the code version of this view. I called it when UITableView cellForRowAtIndexPath gets called. But it's no effect.
I prepare the gradient in awakeFromNib().
let colors = [
UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0).cgColor,
UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0).cgColor]
let gradient = CAGradientLayer()
gradient.frame = gradientView.bounds
gradient.colors = colors
gradientView.layer.insertSublayer(gradient, at: 0)
Is there something wrong with my code?
You should use view's boundsinstead of frame, because your layer is inside of the view, and the frame may have an offset.
The layout of the view is changed after awakeFromNib. So you should resize the layer in layoutSubviews of the view. For this create a property gradient and:
let gradient: CAGradientLayer = CAGradientLayer()
override func awakeFromNib() {
...
let colors = [
UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0).cgColor,
UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0).cgColor]
gradient.frame = bounds
gradient.colors = colors
gradientView.layer.insertSublayer(gradient, at: 0)
...
}
override func layoutSubviews() {
super.layoutSubviews()
gradient.frame = bounds
}
EDIT: An alternative is a custom view with own layer class:
public class GradientLayer: UIView {
#IBInspectable var startColor: UIColor! = UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0)
#IBInspectable var endColor: UIColor! = UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0)
override class var layerClass : AnyClass {
return CAGradientLayer.self
}
override func awakeFromNib() {
super.awakeFromNib()
let colors = [ startColor.cgColor, endColor.cgColor ]
if let gradient = self.layer as? CAGradientLayer {
gradient.colors = colors
}
}
}
This is more elegant, because you can replace the static colors with IB inspectables, and you have a reusable component view.
override func layoutSubviews() {
super.layoutSubviews()
if let gradient = baseView.layer.sublayers?[0] as? CAGradientLayer {
gradient.frame = self.bounds
}
}
After adding gradient layer in navigation bar, I don't see any right/left bar button items when i run on iOS 11. But the same code displays well on iOS 10/9..
Can anyone provide your valuable suggestions to fix this
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setUpGradientNavigationBar()
}
func setUpGradientNavigationBar() {
let lightRedColor = UIColor(red: CGFloat(197/255.0), green: 47/255.0, blue: 40/255.0, alpha: 1.0).cgColor
let mediumRedColor = UIColor(red: CGFloat(176/255.0), green: 42/255.0, blue: 36/255.0, alpha: 1.0).cgColor
let darkRedColor = UIColor(red: CGFloat(106/255.0), green: 25/255.0, blue: 22/255.0, alpha: 1.0).cgColor
let colors = NSArray(objects: lightRedColor, mediumRedColor, darkRedColor)
let gradientLayer = getGradientLayerForColors(colors, location: 0.5, andFrame: self.navigationController?.navigationBar.bounds)
self.navigationController?.navigationBar.barTintColor = UIColor.black
self.navigationController?.navigationBar.layer.insertSublayer(gradientLayer, at: 1)
self.navigationController?.navigationBar.tintColor = UIColor.white
self.navigationController?.navigationBar.topItem?.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: nil, action: nil)
}
func getGradientLayerForColors(_ colors: NSArray, location:CGFloat, andFrame frame:CGRect?) -> CAGradientLayer {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = colors as [AnyObject]
gradientLayer.locations = [0.0,NSNumber.init(value: Float(location))]
gradientLayer.frame = frame!
return gradientLayer
}
Swift 5
Includes status bar in gradient.
Doesn't use an image.
Uses transparency so content is visible through nav bar.
extension UINavigationBar {
func addGradient(_ toAlpha: CGFloat, _ color: UIColor) {
let gradient = CAGradientLayer()
gradient.colors = [
color.withAlphaComponent(toAlpha).cgColor,
color.withAlphaComponent(toAlpha).cgColor,
color.withAlphaComponent(0).cgColor
]
gradient.locations = [0, 0.8, 1]
var frame = bounds
frame.size.height += UIApplication.shared.statusBarFrame.size.height
frame.origin.y -= UIApplication.shared.statusBarFrame.size.height
gradient.frame = frame
layer.insertSublayer(gradient, at: 1)
}
}
My app has a gradient layer that I made in code. However when I display this onscreen it covers all the other components and hides my buttons, labels and images.
How do I push this layer back so its the background of the view?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//creating color gradient
let topColor = UIColor(red: 69/255, green: 140/255, blue: 68/255, alpha: 1).CGColor
let bottomColor = UIColor(red: 143/255, green: 239/255, blue: 141/255, alpha: 1).CGColor
let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.view.frame
gradientLayer.colors = [topColor,bottomColor]
gradientLayer.locations = [0.1,1.0]
self.view.layer.addSublayer(gradientLayer)
}
You can insert a sublayer at a specific index.
self.view.layer.insertSublayer(gradientLayer, at: 0)
We can also add a subview below or above any other views using insertSubview
self.view.insertSubview(subview1_name, belowSubview: subview2_name)
self.view.insertSubview(subview1_name, aboveSubview: subview2_name)
You can add any of the subviews you have at any index as:
self.view.layer.insertSublayer(yourLayer, at: 0)
at also can be used as atIndex, and it means the indexPath of the view (from the view hierarchy), where you want to add your subview at.
When I put the device in mode landscape, the background is set wrong. How do I fix it? I also could use to know how to put the entire application in landscape mode.
override func viewDidLoad() {
super.viewDidLoad()
//BACKGROUND FONDO
//A linear Gradient Consists of two colours: top colour and bottom colour
let topColor = UIColor(red: 15.0/255.0, green: 118.0/255.0, blue: 128.0/255.0, alpha: 1.0)
let bottomColor = UIColor(red: 84.0/255.0, green: 187.0/255.0, blue: 187.0/255.0, alpha: 1.0)
//Add the top and bottom colours to an array and setup the location of those two.
let gradientColors: [CGColor] = [topColor.CGColor, bottomColor.CGColor]
let gradientLocations: [CGFloat] = [0.0, 1.0]
//Create a Gradient CA layer
let gradientLayer: CAGradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColors
gradientLayer.locations = gradientLocations
gradientLayer.frame = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, atIndex: 0)
} //FIN BACKGROUND GRADIENT
In your case gradient is a Layer, not View. It means that it will not resize or change position while the containing layer changes (e.g. during rotation). You have to change the frame of the sublayer manually during rotation.
var gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
createGredientBackground()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
gradientLayer.frame = view.layer.bounds
}
func createGredientBackground() {
let colorTop = UIColor(red: 255.0/255.0, green: 149.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
let colorBottom = UIColor(red: 255.0/255.0, green: 94.0/255.0, blue: 58.0/255.0, alpha: 1.0).cgColor
gradientLayer.colors = [colorTop, colorBottom]
gradientLayer.locations = [0.0, 1.0]
gradientLayer.frame = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, at:0)
}