6

I have been trying to figure out for quite a while now about how to add a gradient layer to the tableView, and have tried many different things, but I can never get the table view cells to show, no matter how many bringSubviews or sendSubviews I do.

let gradientLayer = CAGradientLayer()

gradientLayer.frame = view.bounds

gradientLayer.colors = [UIColor(red: 125/255.0, green: 125/255.0, blue: 125/255.0, alpha: 1.0).cgColor, UIColor(red: 125/255.0, green: 125/255.0, blue: 255/255.0, alpha: 1.0).cgColor]

gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 1.0)

tableView.layer.addSublayer(gradientLayer)

No matter how many combinations of bring subviews and send subviews are done, I always seem to get this and the cells won't come to the front:

enter image description here

Does anyone know how to fix this, or how to do what I want to do another way to make it work?

Any help is much appreciated, thanks.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
D-A UK
  • 1,084
  • 2
  • 11
  • 24

2 Answers2

8

Create background view and assign it to TableView:

func setGradientToTableView(tableView: UITableView, _ topColor:UIColor, _ bottomColor:UIColor) {

    let gradientBackgroundColors = [topColor.CGColor, bottomColor.CGColor]
    let gradientLocations = [0.0,1.0]

    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = gradientBackgroundColors
    gradientLayer.locations = gradientLocations

    gradientLayer.frame = tableView.bounds
    let backgroundView = UIView(frame: tableView.bounds)
    backgroundView.layer.insertSublayer(gradientLayer, atIndex: 0)
    tableView.backgroundView = backgroundView
}

Also clear color of TableView cell:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.backgroundColor = UIColor.clearColor()
}
AGM Tazim
  • 2,213
  • 3
  • 16
  • 25
  • I am not using a Tableview controller. How would I do it for a normal view controller. – D-A UK Dec 31 '17 at 10:19
  • Just put all the code where you originally had it and remove the `sender.` from before the tableView. – Upholder Of Truth Dec 31 '17 at 10:21
  • In Swift 4 it should be `backgroundView.layer.insertSublayer(gradientLayer, at: 0)`. Also don't forget if the layout of the tableView changes (rotation, etc) then the gradient layer will not follow it. You will need to override `viewDidLayoutSubviews` and update the layer there. Otherwise a nice solution so have an upvote. – Upholder Of Truth Dec 31 '17 at 10:22
  • Gradient works, but the clear colour bit doesn't: https://imgur.com/a/wy7Kg – D-A UK Dec 31 '17 at 10:25
  • I fixed the clear colour of cells bit, but there seems to be a problem on my physical iPad Pro. How do I fix this: https://imgur.com/a/1FRPn – D-A UK Dec 31 '17 at 10:36
  • May be its constraint problem. put constraints properly. – AGM Tazim Dec 31 '17 at 10:40
  • If you are using Swift 4 then it should be `cell.backgroundColor = .clear `. You can either put this in the willDisplayCell as in the answer or in your actual UITableViewCell subclass if you are using one or in the cellForRowAt method. – Upholder Of Truth Dec 31 '17 at 10:43
  • @AGMTazim, it is not a constraints problem, because how big the gradient layer is depends on what device I have select in the storyboard when I run the project. It also depends on orientation. How do I fix this? – D-A UK Dec 31 '17 at 10:47
  • As I said earlier this is because the frame of the gradient layer is only set once and therefore if the layout of the tableview changes the gradient layer doesn't. In order to fix this you need to move the definition of backgroundView to a class instance variable then override viewDidLayoutSubviews and add this line `backgroundView.layer.sublayers![0].frame = tableView.bounds`. That way when the layout changes the gradient layer frame will be updated as well. – Upholder Of Truth Dec 31 '17 at 11:02
  • try with changing `let backgroundView = UIView(frame: tableView.bounds)` to `let backgroundView = UIView(frame: tableView.frame)`. and let me know what happens. – AGM Tazim Dec 31 '17 at 11:46
  • Or you can try with `let backgroundView = UIView(frame: view.frame)` – AGM Tazim Dec 31 '17 at 11:55
  • Neither of these will solve the issue. It's not the frame of the backgroundView that is the problem as that is kept the same as the table view by it being the table views background. The problem is the frame of the gradientLayer is never being updated hence why you need to fix that in the viewDidLayoutSubviews. – Upholder Of Truth Dec 31 '17 at 12:15
1

@AGM Tazim

Thanks for that snippet of code. I tweaked it a bit to account for the upgraded swift language for 'cGColor' and specified the start and end point of the gradient.

Hope this is helpful to anyone wanting to make it more customizable

    func setGradientToTableView(tableView: UITableView, _ topColor:UIColor, _ bottomColor:UIColor) {

    let gradientBackgroundColors = [topColor.cgColor, bottomColor.cgColor]


    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = gradientBackgroundColors
    gradientLayer.locations = [0.0,1.0]
    gradientLayer.startPoint = CGPoint(x: 0, y: 0)
    gradientLayer.endPoint = CGPoint(x: 0, y: 1)
    gradientLayer.frame = tableView.bounds
    let backgroundView = UIView(frame: tableView.bounds)
    backgroundView.layer.insertSublayer(gradientLayer, at: 0)
    tableView.backgroundView = backgroundView
}
ivan ramirez
  • 71
  • 1
  • 1