Difference drawing on CALayer and UIView

I have one component that has an UIView subclass and a custom CAlayer into it.

In the UIView there is a circle that is drawn with CoreGraphics, and this is the code:

CGRect b = self.bounds;

int strokeSize = 2;
CGRect arcBounds = CGRectMake(b.origin.x+1, b.origin.y+1, b.size.width-2, b.size.height-2);

CGContextSaveGState(ctx); {     
    CGContextSetLineWidth(ctx, strokeSize);
    CGContextSetStrokeColorWithColor(ctx, [UIColor lightGrayColor].CGColor);
    CGContextStrokeEllipseInRect(ctx, arcBounds);
} CGContextRestoreGState(ctx);

when I draw that circle in the drawRect method inside the UIView it works perfect and the circle is drawn smooth and looks great.

The problem appears when I draw another circle just over this one, but the second one is drawn in the CALayer, actually in the drawInContext method of my custom CALayer. Using just the same code the circle doesn't looks good, and have some "pixellation" on the borders.

Any clues on what can be happening? Thanks in advance.

Upvotes: 3

Views: 1293

Answers (1)

Tiago
Tiago

Reputation: 3151

This is due to the contentsScale property. When you have a custom CALayer the default value of this property is 1.0.

The default value of this property is 1.0. For layers attached to a view, the view changes the scale factor automatically to a value that is appropriate for the current screen. For layers you create and manage yourself, you must set the value of this property yourself based on the resolution of the screen and the content you are providing. Core Animation uses the value you specify as a cue to determine how to render your content. Source.

If you have a retina device and you draw with the contentsScale set to 1.0, it will result in that pixelated look you described. In order to fix this you should set the layer's contentsScale to the one of the screen.

[self.layer setContentsScale:[[UIScreen mainScreen] scale]];

This issue does not happen when you draw the circle in the drawRect method of your UIView since there the default contentsScaleFactor is already the one of the screen.

For views that implement a custom drawRect: method and are associated with a window, the default value for this property is the scale factor associated with the screen currently displaying the view. Source.

Upvotes: 4

Related Questions