How to Make Cells Have a Gradient Background

gradient layer in Swift UITableView

The problem is that the gradientLayer does not update its bounds when the frame of the superview changes - so when the superview changes its frame, the gradientLayer will still keep the same bounds. You need to update its bounds in layoutSubviews.

I would go with @Jay's answer, but there are some issues there:

var gradientLayer: CAGradientLayer = CAGradientLayer()


override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)

// insert it only once
gradientLayer.colors = [UIColor.black.cgColor, UIColor.darkGray.cgColor ]
contentView.layer.insertSublayer(gradientLayer, at: 0)

}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func layoutSubviews() {
super.layoutSubviews()
// here we just need to update the frame
gradientLayer.frame = contentView.frame
}

I have tested it and it works just fine (well, @Jay's answer seems to be working too for that matter).

Add gradient background for only last 2 section on UITableView

This is actually pretty easy.

demo

First, make sure each cell has a transparent background color. The default is opaque white. You can set this in your storyboard, or you can do it in your tableView:cellForRowAtIndexPath: method like this:

cell.backgroundColor = [UIColor clearColor];

Next, make a subclass of UITableView and override layoutSubviews. Be sure to call [super layoutSubviews].

In your override of layoutSubviews, the first time it's called, make a CAGradientLayer with your chosen gradient and add it as a sublayer of the table view's layer at index 0 (so it's behind all of the table view's other sublayers). On every call, update the frame of the gradient layer to be the union of [self rectForSection:1] and [self rectForSection:2].

Also, remember to set the custom class of the table view in your storyboard.

Here's the table view subclass I used to make the demo.

GradientTableView.h

#import <UIKit/UIKit.h>

@interface GradientTableView : UITableView

@end

GradientTableView.m

#import "GradientTableView.h"

@implementation GradientTableView {
CAGradientLayer *gradientLayer;
}

- (void)layoutSubviews {
[super layoutSubviews];
[self layoutGradient];
}

- (void)layoutGradient {
[self createGradientLayerIfNeeded];
[self updateGradientLayerFrame];
}

- (void)createGradientLayerIfNeeded {
if (gradientLayer != nil) {
return;
}

gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = @[
(__bridge id)[UIColor redColor].CGColor,
(__bridge id)[UIColor orangeColor].CGColor
];
gradientLayer.locations = @[ @0, @1 ];
gradientLayer.startPoint = CGPointZero;
gradientLayer.endPoint = CGPointMake(0, 1);
gradientLayer.type = kCAGradientLayerAxial;

[self.layer insertSublayer:gradientLayer atIndex:0];
}

- (void)updateGradientLayerFrame {
CGRect frame = [self rectForSection:1];
frame = CGRectUnion(frame, [self rectForSection:2]);
gradientLayer.frame = frame;
}

@end

How to make gradient background in UITableViewCell in iOS?

The always-awesome Ray Wenderlich did a tutorial on changing UITableViewCells and includes a gradient.

http://www.raywenderlich.com/2033/core-graphics-101-lines-rectangles-and-gradients

If you want a quick and way, here's some code:

//include #import <QuartzCore/QuartzCore.h> in the header…

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

if (cell == nil) {
cell = [[DayCalendarCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = cell.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor]CGColor], (id)[[UIColor redColor]CGColor], nil];
[cell.layer addSublayer:gradient];
}
return cell;
}

You can change the colors but this will give you a good idea…

Good luck!

Partial background color change of table-cell - gradient issue


Note: There are already few questions regarding hard-stop gradient creation which is why I didn't post my earlier comment as an answer but while searching for a duplicate I figured out there might be a better way to tackle your problem and hence posting the alternate approach as an answer.

Why is there a fade out and blend to white?

Let me get this out of the way before explaining the alternate approach (just for completeness sake). The gradient that you have defined would be interpreted by the UA as follows:

  • Since the first param is to right, the gradient starts at left (that is 0% is at left).
  • From 0% to 50% (that is, from left edge till half way), the color of the gradient is a solid red.
  • Red ends at 50% and white starts only at 51% as per gradient definition and so between 50 - 51% the color slowly changes from red to white (and blends with the white on the other side).
  • From 51% to 100% (that is, from slightly past half way till the right edge), the color is pure white.

This gap between 50% to 51% is generally used for diagonal (or angled) gradients where sharp stops result in jagged (uneven) edges but for normal horizontal or vertical gradients it won't be needed.

Now, I assume that you are trying to change the color stop points like below in order to get partial fill:

background: linear-gradient(to right, red 50%, white 50%); /* for a 50% fill */
background: linear-gradient(to right, red 75%, white 75%); /* for a 75% fill */

But there is a better way to do this than change the color stop points.


What is the better way and why?

A better option would be the one in the below snippet where the color never really changes. Gradient is just a solid red color always but we control it's size/width using background-size property. As you can see in the demo below, this is as effective as changing the color stop points.

This method is more advantageous when you want to animate/transition the background because the background-size is a transitionable property whereas the gradient image's color stop point change is not. You can see what I mean in the below demo. Just hover on each cell and see what happens.





.Row {

display: table;

width: 100%;

table-layout: fixed;

border-spacing: 10px;

}


.Column {

display: table-cell;

background: linear-gradient(red,red); /* use the color you need */

background-repeat: no-repeat; /* dont change */

border: 1px solid; /* just to show cell width */

}


.Column:nth-child(1) {

width:20%;

background-size: 100% 100%; /* change first value for width change */

}

.Column:nth-child(2) {

width:50%;

background-size: 75% 100%; /* change first value for width change */

}

.Column:nth-child(3) {

width:30%;

background-size: 50% 100%; /* change first value for width change */

}


/* just for demo */


.Column { transition: all 1s; }

.Column:nth-child(1):hover { background-size: 50% 100%; }

.Column:nth-child(2):hover { background-size: 100% 100%; }

.Column:nth-child(3):hover { background-size: 75% 100%; }
<div class="Row">

<div class="Column">C1</div>

<div class="Column">C2</div>

<div class="Column">C3</div>

</div>

Setting a gradient background in UITableViewCell

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.



Related Topics



Leave a reply



Submit