Gradient background in grid header cell


#1

Greetings - just getting started using the Shinobi grid in some code I inherited.  I’m attempting to set the background of my header row cells to a gradient.  I thought perhaps I could do this by inserting a CAGradientLayer into the SGridTextCell that I’m using, however this doesn’t seem to work.  When I run my app the grid does not display the gradient in the header rows.  Below is a snippet of the code I’m using the create the cell:

SGridTextCell cell = (SGridTextCell)grid.DequeueReusableCell("headerCell");        
                    if (cell == null)
                    {
                        cell = new SGridTextCell("headerCell"); 
                    }

                    MonoTouch.CoreAnimation.CAGradientLayer gradientLayer = new MonoTouch.CoreAnimation.CAGradientLayer();
                    gradientLayer.Colors = new MonoTouch.CoreGraphics.CGColor[]
                    {
                        UIColor.FromRGB(115, 181, 216).CGColor,
                        UIColor.FromRGB(35, 101, 136).CGColor
                    };
                    gradientLayer.Bounds = cell.Bounds;
                    gradientLayer.Position = cell.Frame.Location;
                    
                    cell.Layer.InsertSublayer(gradientLayer, 0);
                    cell.Layer.MasksToBounds = true;

                    cell.TextField.TextAlignment = UITextAlignment.Center;
                    cell.TextField.BackgroundColor = UIColor.Clear;
                    cell.BackgroundColor = UIColor.Clear;
                    cell.TextField.TextColor = UIColor.White;

Any insight into what I’m missing or doing incorrectly would be appreciated.

Thanks!


#2

Hi ThirteenDaysAWeek,

I’ve had a quick look at your code and there’re a few things to note:

  1. When you are setting  gradientLayer.Bounds = cell.Bounds;  the cell may not have its correct bounds. For example, when you check to see if your dequeued cell is nil, and then create a cell if it is, no frame/bounds are applied to the cell. Setting the size of your gradient layer might be better done every time the cell has its size changed (perhaps by subclassing SGridTextCell) - this would ensure that the gradient layer always has the correct size for the cell.
  2. The next line of code  gradientLayer.Position = cell.Frame.Location;  is setting the location of the gradient within the cell’s coordinate system. So if the cell has a location of {500, 500} then you are setting the gradient to have a location of {500, 500} within the cells coordinate system - this will probably result in gradient layers that are positioned outside the bounds of the cell. It is more likely that you want your gradient to start from the top left of the cell, which means the gradient’s default location of {0, 0} should be fine. However, the same problem from 1. also exists here - the cells may not be positioned correctly at this point.
  3. Every time we enter this data source method for a cell you are adding a gradient layer to it. This could be problematic as the grid recycles cells for performance reasons - this means that if your  DequeueReusableCell  returns a cell (the nil check fails), it already has a gradient layer from previous use. There are a few ways to remedy this; such as checking to see if a gradient layer already exists before adding one, or only adding a gradient layer when instantiating a cell (in your check for nil, or in the init method of an SGridTextCell subclass). 

I hope the above gives you some idea as to why you were not seeing a gradient layer in your cells and possible ways to fix this!  :smile:


#3

Thanks for your response.  I ended up getting things working by removing the lines of code that set the bounds and position of the gradient layer and instead setting the gradient’s frame to an explicit size.  This seems to do the trick, however as you pointed out in #3, I’m adding a new gradient layer everytime GetCell is called, so I’ve adjusted my code to only add the gradient if I’m creating a new cell.

Thanks again!

Chris