Swift: gradient on a cell of a tableview

本秂侑毒 提交于 2019-12-31 05:23:04

问题


On tableView's cells, I'm trying to define a gradient with the following Swift code:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

    var cell:UITableViewCell = self.tableView?.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
    cell.backgroundColor=UIColor.clearColor()
    let gradient : CAGradientLayer = CAGradientLayer()
    var arrayColors:Array<AnyObject> = [UIColor.blackColor().CGColor, UIColor.whiteColor().CGColor]
    gradient.colors=arrayColors
    gradient.frame = cell.bounds
    cell.layer.insertSublayer(gradient, atIndex: UInt32(indexPath.row))

    return cell
 }

The behavior is very chaotic: when the view is first loaded, all cells have a white background. And if I scroll up and down, some content's cells disappear (title and subtitle) and the gradient finally appears in these cells (randomly, some other cells stay with a white background). Is it related to this cast -> UInt32(indexPath.row) ?


回答1:


The gradient is a visual ornamentation. It is specific to the cell class. How the cell looks is the responsibility of the cell. It should be defined in the cell class then. It absolutely does not belong to the cellForRowAtIndexPath which should be solely about choosing the right cell for the right row. But you are configuring the internals of the cell in that method and this, combined with the way how queueing works, causes all the issues.

1) Create a subclass of UITableViewCell (programatically, IB..it doesn't really matter)

2) Add the layer in awakeFromNib or layoutSubviews to the backroundView property.

3) register the cell in viewDidLoad in your tableViewController.




回答2:


I had a similar problem, my mistake was inserting the new layer with gradient directly in the cell, try inserting the new layer to the backgroundView something like this

let gradient = CAGradientLayer()
// layer setup...
cell.backgroundView = UIView()
cell.backgroundView?.layer.insertSublayer(gradientLayer, atIndex: 0)

Hope this helps.




回答3:


Further expanding Earl Grey, and hidra Answer,

when you add a gradient to a specific view then you need to set the actual frame for the gradient layer.

if your view on which you have added gradient layer loaded initially on view did load then you have to put it in then it will not resize as expected, you can resolve this problem in two ways.

first : Give frame manually by calculating the size of the view, but this is very hectic as you have to calculate for each iPhone variation you can calculate the width and height ratio BY.

 let bounds = UIScreen.main.bounds
 let deviceheight = bounds.size.height
 let deviceWidth = bounds.size.width

Then you calculate and give the width size

another way you can do it by doing no calculation just by adding the layer after view has been loaded which can be done with:

 override func viewDidAppear(_ animated: Bool) {
    Your gradient code //you can create a method for adding a gradient layer 
}

Now in Tableview or collection view the same problem exists and we don't have any view did appear method in the cell. we have two scenarios in this.

  1. data is static.
  2. data is coming from the server

coming up to the first scenario when data is static you all have to do it as create a variable of boolean type and make it false till once the view is loaded. then make it true in view did appear method for row at index method and again reload cell.

class VC: UIViewController {


var isCellLoaded : Bool = false

override func viewDidAppear(_ animated: Bool) {

    isCellLoaded = true
    self.aTable.reloadData()
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {



    let cell = tableView.dequeueReusableCell(withIdentifier: "youcellidentifier", for: indexPath) as! youcell 
    if isCellLoaded {
        cell.gradientView.setGradient(cornerRadius: 5, gradientLeftColor: .notificationViewLeftColor, gradientRightColor: .notificationViewRightColor)
        if let gradient = cell.gradientView.layer.sublayers?[0] as? CAGradientLayer {
            gradient.frame = cell.gradientView.bounds
        }
    }

    return cell
}

Coming to the second scenario when the data is coming from API

Hurray!! you don't need to do anything as for the first time there is no data in the till api has not given any response and when the response comes you have to reload data. and things will work perfectly. Blockquote



来源:https://stackoverflow.com/questions/25556603/swift-gradient-on-a-cell-of-a-tableview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!