I'm doing a CAGradientLayer
for every background of my UIView
s, but I have a small problem. The gradient doesn't seem that smooth enough. The transition between the colors are to present. You can see it in this picture.
This is how I implemented this gradient in the initializer of my UIView.
CAGradientLayer *layer = [CAGradientLayer layer];
layer.colors = [NSArray arrayWithObjects:
(id)[[UIColor darkKinepolisColor] CGColor],
(id)[[UIColor lightKinepolisColor] CGColor],
(id)[[UIColor lightKinepolisColor] CGColor],
(id)[[UIColor darkKinepolisColor] CGColor],
nil];
layer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0],
[NSNumber numberWithFloat:0.4],
[NSNumber numberWithFloat:0.6],
[NSNumber numberWithFloat:1],
nil];
layer.startPoint = CGPointMake(0, 0);
layer.frame = self.layer.bounds;
layer.endPoint = CGPointMake(1, 1);
layer.contentsGravity = kCAGravityResize;
[self.layer addSublayer:layer];
Could you, fine developers, help me with this problem? Thanks!
From what I've seen CAGradientLayer does not support dithering, but CGGradient does. See my answer here. Also see the other answers for example on using CGGradient.
Isn't this just a consequence of 8-bit colour values? The steps between the colours are as small as they can possibly be.
i.e. if you want a gradient between rgb(100,100,100) and rgb(109,109,109) it can only be perfectly smooth across a gradient width of 10 pixels. If you tried to draw this gradient across a width of 100 pixels you would get 10 blocks of colour 10px wide and it would look very blocky. What else could happen?
You can make it appear smoother by dithering and adding noise but there is no built in function for this.
So, either, choose colours farther apart, draw the gradient over a shorter distance or make the graphic in Photoshop and apply noise and dithering to make it appear smoother.
I'm developing an app that needs a base gradient, and various other gradients are faded into it, depending on various factors (eg: the time of day). I've found that I can continue to use CAGradientLayer for all but the base gradient. For the base gradient, i created it in photoshop and added 0.554% noise. Almost imperceptible, but it prevents the banding effect when I animate the alpha of CAGradientLayer
s above it.
So I guess the answer would be that you need dithering/noise on at least one of the gradients to avoid the banding effect. It may also be possible to add this programmatically, or by loading a pre-rendered black image with noise over a CAGradientLayer with a low alpha (~0.1f) on the noise layer.
Rasterize with your device's screen scale, will be very smooth and crisp!
[layer setShouldRasterize:YES];
[layer setRasterizationScale:[UIScreen mainScreen].scale];