me2
me2

Reputation: 13

Setting a gradient background in UITableViewCell

im trying to create a tableview controller where every cell has a gradient as background.

So my approach was the code below, it sets the correct colors but when scrolling the colors appear as they were set randomly.

I dont know where the error is. The textLabels will be set properly but the colors not.

import UIKit


class ResourceOverViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let reuseIdentifier = "OverViewCell"
@IBOutlet weak var prototypeCell: UITableViewCell!
@IBOutlet weak var tableView:UITableView!
var resourceInMissions:[ResourceInMission] = [ResourceInMission]()
var whiteRussian:Int64 = Int64()
var Caipirinha:[String] = [String]()
var Avails:[CAGradientLayer] = [CAGradientLayer]()


override func viewDidLoad() {
    self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: reuseIdentifier)
    super.viewDidLoad()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source


override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    setView()

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return Caipirinha.count
}


func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    print(indexPath)

    cell.textLabel?.backgroundColor = UIColor.clear
    cell.textLabel?.isOpaque = true
    cell.isOpaque = true

    var gradient = Avails[indexPath.row]
    gradient.frame = cell.bounds

    cell.textLabel?.layer.insertSublayer(gradient, at: 0)

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)
    cell.textLabel?.text = Caipirinha[indexPath.row]

    return cell
}



func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
    var index: IndexPath = indexPath
    let cell = tableView.cellForRow(at: indexPath)
    whiteRussian = resourceInMissions[indexPath.row].getID()



    guard let vc = UIStoryboard(name:"Main", bundle:nil).instantiateViewController(withIdentifier: "ShowResource") as UIViewController? else {
        print("Could not instantiate view controller with identifier of type SecondViewController")
        return
    }

    vc.setObjectID(idToTransfer: whiteRussian)
    present(vc, animated:true, completion: nil)

}

@IBAction func back(){
    //Code is in Extension of UIViewController
    moveBack()

}

func sort(resourceInMissions:[ResourceInMission]) -> [ResourceInMission] {

    var arrayOfArrays = [[ResourceInMission](), [ResourceInMission](), [ResourceInMission](), [ResourceInMission](), [ResourceInMission](), [ResourceInMission]()]
     // At first take the availability to sort.
    // It produces availibility lists
    for element in resourceInMissions {


        // gets the index of the avail. from availibilities array 
        // for every avail a new list is made in arraysOfArray


        if let string = element.getAvailability(){
            if let av = availibilitys.index(of: string){

                arrayOfArrays[av].append(element)

            }
        }

    }



    // Now iterate through each list and sort for the resourceType
    // Idea is: get rsIM from one of the arrays above and put it in a type array for each element
    // after finishing the avail array merge all type arrays for avail list sorted for types
    var arraySorted:[ResourceInMission] = [ResourceInMission]()
    for array in arrayOfArrays {

        // lists have to be initialized for each loop
        // otherwise the lists would be merged
        var type1:[ResourceInMission] = [ResourceInMission]()
        var type2:[ResourceInMission] = [ResourceInMission]()
        var type3:[ResourceInMission] = [ResourceInMission]()
        var type4:[ResourceInMission] = [ResourceInMission]()
        var type5:[ResourceInMission] = [ResourceInMission]()
        var type6:[ResourceInMission] = [ResourceInMission]()
        var type7:[ResourceInMission] = [ResourceInMission]()
        var type8:[ResourceInMission] = [ResourceInMission]()

        for element in array {

            if let id = element.getResourceID(){
                if let resource = Resource().getByIdFromDB(id: id){
                    if let typeID = resource.getResourceTypeID(){

                        switch typeID {
                        case 1:
                            type1.append(element)
                            break
                        case 2:
                            type2.append(element)
                            break
                        case 3:
                            type3.append(element)
                            break
                        case 4:
                            type4.append(element)
                            break
                        case 5:
                            type5.append(element)
                            break
                        case 6:
                            type6.append(element)
                            break
                        case 7:
                            type7.append(element)
                            break
                        case 8:
                            type8.append(element)
                            break
                        default:
                            break
                        }
                    }
                }
            }
        }

        arraySorted = arraySorted + type1 + type2 + type3 + type4 + type5 + type6 + type7 + type8


    }
    return arraySorted
}

func setView(){
    var count = 0


    resourceInMissions = [ResourceInMission]()
    resourceInMissions = try! ResourceInMission().getOverviewList()
    count = resourceInMissions.count


    resourceInMissions = sort(resourceInMissions: resourceInMissions)

    Caipirinha = [String]()
    Avails = [CAGradientLayer]()
    Caipirinha.removeAll()
    for index in 0 ..< resourceInMissions.count {
        Caipirinha.append(resourceInMissions[index].toString())
        let gradient: CAGradientLayer = CAGradientLayer()

        if let av = resourceInMissions[index].getAvailability(){

            switch av {
            case availibilitys[0]:
                //blue
                let blue = [hexStringToUIColor(hex: "#E5EEFF"), hexStringToUIColor(hex: "#93B7FF"), hexStringToUIColor(hex: "#4F8EFF")]
                gradient.colors = blue.map { $0.cgColor }
                Avails.append(gradient)
                break
            case availibilitys[1]:
                //red
                let red = [hexStringToUIColor(hex: "#FFE5E5"), hexStringToUIColor(hex: "#FF8E8B"), hexStringToUIColor(hex: "#FF4F4F")]
                gradient.colors = red.map { $0.cgColor }
                Avails.append(gradient)
                break
            case availibilitys[2]:
                //rose
                let rose = [hexStringToUIColor(hex: "#FFFFFF"), hexStringToUIColor(hex: "#FDEADA"), hexStringToUIColor(hex: "#FAC090")]
                gradient.colors = rose.map { $0.cgColor }
                Avails.append(gradient)
                break
            case availibilitys[3]:
                //yellow
                let yellow = [hexStringToUIColor(hex: "#F5FFE6"), hexStringToUIColor(hex: "#F0FB85"), hexStringToUIColor(hex: "#FBF622")]
                gradient.colors = yellow.map { $0.cgColor }
                Avails.append(gradient)
                break
            case availibilitys[4]:
                //green
                let green = [hexStringToUIColor(hex: "#F5FFE6"), hexStringToUIColor(hex: "#C8FB85"), hexStringToUIColor(hex: "#BCFB5F")]
                gradient.colors = green.map { $0.cgColor }
                Avails.append(gradient)
                break
            case availibilitys[5]:
                //grey
                let gray = [hexStringToUIColor(hex: "#F2F2F2"), hexStringToUIColor(hex: "#E9E9E9"), hexStringToUIColor(hex: "D9D9D9")]
                gradient.colors = gray.map { $0.cgColor }
                Avails.append(gradient)
                break
            default:
                break
            }
        }


    }
    self.tableView.reloadData()
   }
}    

Upvotes: 1

Views: 734

Answers (2)

James P
James P

Reputation: 4836

The reason your gradients appear random is because of cell re-use.

cell.textLabel?.layer.insertSublayer(gradient, at: 0)

This line is getting called every time you display a cell, so it works the first time but as your cells get reused the new gradients are just getting added behind the old ones.

You can either remove the old gradient layer before adding a new one, or create a UITableViewCell subclass with a gradient layer that can be updated.

Upvotes: 0

Kuntal Gajjar
Kuntal Gajjar

Reputation: 802

Your approach seems to be wrong to me.

You need to do below things 1) create a sub class of UIView having name GradientBackgroundView and draw a gradient on drawrect of this view 2) On your storyboard, add uitableviewcell to your tableview and add GradientBackgroundView as a background of cell

Hope this will help you

Upvotes: 1

Related Questions