Home > OS >  Problem with gradient on the background of a table swift
Problem with gradient on the background of a table swift

Time:12-24

I have a tableview with the cells and I want apply a custom gradient. I've searched here but nothing works with my code.

My part of the code where I try to add the gradient

  override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Menú Principal"
        tableView.backgroundView?.aplicarDegradadoDeportes() 
        self.navigationItem.setHidesBackButton(true, animated: true)      
    }

This is my function for the gradient

 func aplicarDegradadoDeportes() {
        let colorInicio =  UIColor(red: 255/255, green: 59/255, blue: 0/255, alpha: 1.0).cgColor
        let colorFin = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0).cgColor
     let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [colorInicio, colorFin]
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
    
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
        gradientLayer.frame = self.bounds
        
        self.layer.insertSublayer(gradientLayer, at:0)
    }

Please help

CodePudding user response:

The backgroundView property of UITableView is nil by default. So your aplicarDegradadoDeportes function is never actually called.

Set a view as the backgroundView then it should work.

override func viewDidLoad() {
    super.viewDidLoad()
    self.title = "Menú Principal"
    let background = UIView()
    tableView.backgroundView = background
    background.aplicarDegradadoDeportes()
    self.navigationItem.setHidesBackButton(true, animated: true)      
}

The only issue is that the tableView will update the size of backgroundView as needed but your additional layer may not automatically get resized to match.

One solution is to move the code to setup the background view in viewWillAppear or you can override viewDidLayoutSubviews and update the layer's frame.

The best solution is to create a custom UIView subclass that draws the gradient so it stays up to date as it is sized.

class GradientView: UIView {
    var gradient: CALayer!

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        if superview != nil {
            let colorInicio =  UIColor(red: 255/255, green: 59/255, blue: 0/255, alpha: 1.0).cgColor
            let colorFin = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0).cgColor
            let gradientLayer = CAGradientLayer()
            gradientLayer.colors = [colorInicio, colorFin]
            gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
            gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
            gradientLayer.frame = self.bounds

            self.layer.insertSublayer(gradientLayer, at:0)
            gradient = gradientLayer
        }
    }

    override var frame: CGRect {
        didSet {
            gradient?.frame = bounds
        }
    }
}

Then your view controller viewDidLoad becomes:

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = "Menú Principal"
    let background = GradientView()
    tableView.backgroundView = background
    self.navigationItem.setHidesBackButton(true, animated: true)      
}

CodePudding user response:

You could create a custom UITableViewCell subclass and override the layoutSubviews() function.

For example like this:

class GradientTableViewCell: UITableViewCell {
    // Property to store the gradient layer
    private var gradientLayer: CAGradientLayer?
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // Check if gradient layer already exists
        if gradientLayer == nil {
            // Set the colors for the gradient
            let colorInicio =  UIColor(red: 255/255, green: 59/255, blue: 0/255, alpha: 1.0).cgColor
            let colorFin = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0).cgColor
            
            // Create the gradient layer and set its properties
            gradientLayer = CAGradientLayer()
            gradientLayer?.colors = [colorInicio, colorFin]
            gradientLayer?.startPoint = CGPoint(x: 0.0, y: 0.5)
            gradientLayer?.endPoint = CGPoint(x: 1.0, y: 0.5)
            gradientLayer?.frame = self.bounds
            
            // Add the gradient layer as a sublayer to the cell's content view
            self.contentView.layer.insertSublayer(gradientLayer!, at:0)
        }
    }
}

In your controller you need the set the cell class to GradientTableViewCell:

override func viewDidLoad() {
  super.viewDidLoad()
  self.title = "Menú Principal"
  self.navigationItem.setHidesBackButton(true, animated: true)

  // Set the cell class for the table view to be GradientTableViewCell
  self.tableView.register(GradientTableViewCell.self, forCellReuseIdentifier: "Cell")
}

In the cellForRowAt function of your table data dequeue a GradientTableViewCell instead of UITableViewCell

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  // Dequeue a GradientTableViewCell instead of a UITableViewCell
  let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! GradientTableViewCell

  // Configure the cell as needed

  return cell
}

Now you should be able to set the gradient to the background of the cells

  • Related