How to set background of a view (UITableview) with dynamic cells? - ios

I am trying to set a background Colour to the view occupied by the UITableViewCell. I have dragged an outlet and have a gradient layer which i return to it
extension CAGradientLayer{
func viewGradient(topColour:UIColor,bottomColour : UIColor) -> CAGradientLayer{
let gradientColor: [CGColor] = [topColour.cgColor, bottomColour.cgColor]
let gradientLocations: [Float] = [0.0/1.0]
let gradientLayer: CAGradientLayer = CAGradientLayer()
gradientLayer.colors = gradientColor
gradientLayer.locations = gradientLocations as [NSNumber]?
return gradientLayer
}
}
And i access this method in my viewDidLoad method of a view controller
let bottomColour = UIColor(red: (0.018), green: (0.38), blue: (0.64), alpha: 1.0)
let topColour = UIColor(red: (0.13), green: (0.63), blue: (0.67), alpha: 0.7)
let background = CAGradientLayer().viewGradient(topColour:topColour,bottomColour : bottomColour)
background.frame = self.view.bounds
self.view.layer.insertSublayer(background, at: 0)
myMenu.layer.insertSublayer(background, at: 0)
I have dynamic cells in my table view and as the number of cells increases the view slides down and i Have to scroll to see my cells.I have white spaces. Is there any way i can set the entire scrolling region to have my background gradient colour or am i missing something ?
Here is the screenshot of the images showing my exact problem

As commented above, UITableView has a backgroundView property.
In your viewDidLoad method, keep your background constant declared as is, then below add:
self.tableView.backgroundView = background
Hope that helps.

Related

Create Gradient in View With locations from zeplin

I am working on a project where i need to apply gradients to the view. I am having sketch file and have colors which i am going to use for gradient with the locations but i am unable to get the exact view.
Can anyone please help how to get that?
I have created a function to apply gradient:-
func applyGradient(colours: [UIColor]) -> Void {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = colours.map { $0.cgColor }
self.layer.insertSublayer(gradient, at: 0)
}
func applyGradientToView(){
let firstColor = UIColor(red: 26/255, green: 169/255, blue: 186/255, alpha: 1.0)
let secondColor = UIColor(red: 26/255, green: 97/255, blue: 157/255, alpha: 1.0)
let thirdColor = UIColor(red: 27/255, green: 65/255, blue: 144/255, alpha: 1.0)
self.applyGradient(colours: [firstColor, secondColor, thirdColor])
}
Here array UIcolor is a combination of colors to be used, I used all three but still, I didn't get the same as in the sketch
What I created :-
Gradient colors in sketch file:-
The view in sketch file is like this:-
Couple issues...
1) Your "Gradient colors in sketch file:" image does not match your Sketch file output image. However you applied the gradient in sketch, it is not a full top-to-bottom (or, in this case, bottom-to-top) gradient fill.
2) When working with colors in different applications and/or devices, you have to be aware of "color spaces". Take a quick search on google for sketch colors don't match and you'll find lots of material explaining it, along with tips on using sketch for iOS targets.
So, an easy way to get close to your desired output is to use OS X Digital Color Meter - which should be installed by default on your Mac (if it's not, it's easy to find). That tool allows you to hover over a point on your image and get the RGB values based on different color spaces. SRGB should be a match.
Also, there is a better way to code your custom view for reuse. Take a look at this approach:
class MyGradientView: UIView {
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
let gradientLayer = layer as! CAGradientLayer
let firstColor = UIColor(red: 25/255, green: 138/255, blue: 173/255, alpha: 1.0)
let secondColor = UIColor(red: 27/255, green: 163/255, blue: 184/255, alpha: 1.0)
let colours = [firstColor, secondColor]
gradientLayer.colors = colours.map { $0.cgColor }
gradientLayer.shadowColor = UIColor.black.cgColor
gradientLayer.shadowOffset = CGSize(width: 0.0, height: 1.0)
gradientLayer.shadowRadius = 2.0
gradientLayer.shadowOpacity = 0.5
gradientLayer.masksToBounds = false
}
}
Gradient layers in iOS by default go from Top-To-Bottom, so you only need your top and bottom colors defined. This approach also includes your shadow (as shown in your sketch output image). And it will maintain the gradient and shadow when using the custom view with auto-layout:
let v = MyGradientView()
view.addSubview(v)
v.translatesAutoresizingMaskIntoConstraints = false
v.topAnchor.constraint(equalTo: view.topAnchor, constant: 100.0).isActive = true
v.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100.0).isActive = true
v.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40.0).isActive = true
v.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40.0).isActive = true
Result:
According to the documentation of CAGradientLayer (https://developer.apple.com/documentation/quartzcore/cagradientlayer) to specify a location of colors you can use locations property(in your case [0, 0.68, 1]):
var locations: [NSNumber]? { get set }
but as #Alladinian wrote in the comment in your example, it looks like your gradient was drawn from bottom to top and start before view and end far after view so you see only a part

Set background in UIViewController inside navigation controller

I want to set my background color fullscreen (includes navigation bar and status bar also) with gradient color. Right now, I made this by creating gradient
func setDefaultColorBackground() {
let colorTop = UIColor(hexString: "804b8a").cgColor
let colorBottom = UIColor(hexString: "42074b").cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [ colorTop, colorBottom]
gradientLayer.locations = [ 0.0, 1.0]
gradientLayer.frame = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, at: 0)
}
So I added layer in my view in ViewController. It works but it does't covered up the status bar and navigation bar. See this image:
I think the background only fill the view under navigation bar. Anyway, I am using .xib and load it up manually in my view controller class.
Is there any ideas how to do it? Thank you so much!
I guess to change the color of the navigation bar you have to write the code for it also something like this :
UINavigationBar.appearance().barTintColor = UIColor.redColor()
or whatever color you want to provide :
UINavigationBar.appearance().barTintColor = UIColor(red: 0, green: 0/255, blue: 205/255, alpha: 1)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor()]
I hope it was helpful to you. Happy Coding :)

Adding a Gradient Background to UITableViewCell Swift

I found this SO question here:
Swift: gradient on a cell of a tableview
I am using a Custom UITableViewCell which has the following code:
public class MyCustomUITableViewCell: UITableViewCell {
override public func layoutSubviews() {
super.layoutSubviews()
//setting backgroundColor works
//self.backgroundColor = UIColor.brownColor()
self.backgroundColor = UIColor.clearColor()
let colorTop = UIColor(red: 192.0/255.0, green: 38.0/255.0, blue: 42.0/255.0, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 35.0/255.0, green: 2.0/255.0, blue: 2.0/255.0, alpha: 1.0).CGColor
let gradient = CAGradientLayer()
gradient.colors = [ colorTop, colorBottom]
gradient.locations = [ 0.0, 1.0]
self.backgroundView = UIView()
//setting view backgroundColor does not work
//self.backgroundView?.backgroundColor = UIColor.redColor()
self.backgroundView!.layer.insertSublayer(gradient, atIndex: 0)
}
}
The UITableViewCells displayed are clear because I set the self.backgroundColor to UIColor.clearColor().
The gradient does not show, and if, instead of adding a gradient to the UITableViewCell.backgroundView,I just set the UITablveViewCell.backgroundView.backgroundColor to UIColor.redColor(), that does not work either.
When I create the UITableViewCell.backgroundView at this line of code:
self.backgroundView = UIView()
I am assuming the backgroundView automatically fills the bounds of the UITableViewCells displayed in the UITableView, in other words, backgroundView is not a 0x0 width x height correct?
This might help you and others: it's the (tiny) UIView subclass I use to draw gradients without having to get into the mess of inserting CALayers. This way UIView handles resizing using things like Auto Layout, which is much easier to work with.
Put this code into a file in your project, then use it as a normal view. It can go straight into your cell's background view if you want. You should be able to customise the colours in code or in IB if you use it that way.
It's trivial code, but please consider it CC-0 licensed – i.e. public domain where possible, "just use it however you want" everywhere else.
#IBDesignable class GradientView: UIView {
#IBInspectable var firstColor: UIColor = UIColor.whiteColor()
#IBInspectable var secondColor: UIColor = UIColor.blackColor()
override class func layerClass() -> AnyClass {
return CAGradientLayer.self
}
override func layoutSubviews() {
(layer as! CAGradientLayer).colors = [firstColor.CGColor, secondColor.CGColor]
}
}
If you're looking for more advanced functionality, try something like SwiftyGradient – it does much the same thing (i.e. pushing the work into a UIView to make things easier), but has more functionality.
As noted in the documentation for UITableViewCell:
If you want to change the background color of a cell, do so in the
tableView:willDisplayCell:forRowAtIndexPath: method of your table view
delegate.
I normally just add another view to my cells that I use as background view, that works in all cases.

Swift ViewController doesn't refresh background color

I have a MainView Controller and a second SettingsView Controller.
In SettingsView controller, I let user select a background color, save it and move back to MainView Controller.
I use Navigation controller segue to move from Main to Settings and use dismissViewControllerAnimated to move back to Main.
My problem is when I set background for main view, it doesn't show up.
But if I close and restart app then it comes up correctly.
Is it because Main view is already open and not refreshed back?
Here is the code:
Settings:
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("theme", forKey: "BackgroundColor")
Main:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clearColor()
var backgroundLayer = Util.GetTheme()
backgroundLayer.frame = view.frame
view.layer.insertSublayer(backgroundLayer, atIndex: 0)
}
As per your requirement, you need to move the code for changing color to viewWillAppear method. Since viewDidLoad will be called only once at the time when it get loaded to memory. viewWillAppear will be called each time it will come to foreground or visible to user.
But where you are saving selected color and applying the saved color?
Try This code :
class Colors {
let colorTop = UIColor(red: 192.0/255.0, green: 38.0/255.0, blue: 42.0/255.0, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 35.0/255.0, green: 2.0/255.0, blue: 2.0/255.0, alpha: 1.0).CGColor
let gl: CAGradientLayer
init() {
gl = CAGradientLayer()
gl.colors = [ colorTop, colorBottom]
gl.locations = [ 0.0, 1.0]
}
}

SevenSwitch UI background color in iOS 8

I am using the SevenSwitch control instead of the built in UISwitch. Instead of an on and off mode I want both sides to have the same background color.
I tried the following code:
let mySwitch = SevenSwitch()
let switchTintColor = UIColor(red: 109/255, green: 59/255, blue: 100/255, alpha: 1.0)
mySwitch.offLabel.backgroundColor = switchTintColor
mySwitch.onTintColor = switchTintColor
mySwitch.borderColor = switchTintColor
That gets really close to what I want except for the background behind the thumb view when the switch is off.
You'll want to set the activeColor and inactiveColor properties on the switch. That should get you what you're after.
mySwitch.activeColor = switchTintColor
mySwitch.inactiveColor = switchTintColor

Resources