Ich versuche, mit einem CAShapeLayer einen gestrichenen Kreis zu zeichnen und eine Kreisbahn darauf zu setzen. Diese Methode ist jedoch beim Rendern auf dem Bildschirm durchweg weniger genau als die Verwendung von borderRadius oder das direkte Zeichnen des Pfads in einem CGContextRef.
Hier sind die Ergebnisse aller drei Methoden:
Beachten Sie, dass der dritte Teil schlecht gerendert ist, insbesondere innerhalb des Strichs oben und unten.
Ich habe die contentsScale
Eigenschaft auf gesetzt [UIScreen mainScreen].scale
.
Hier ist mein Zeichnungscode für diese drei Kreise. Was fehlt, damit der CAShapeLayer reibungslos zeichnet?
@interface BCViewController ()
@end
@interface BCDrawingView : UIView
@end
@implementation BCDrawingView
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
self.backgroundColor = nil;
self.opaque = YES;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
[[UIColor whiteColor] setFill];
CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), NULL);
[[UIColor redColor] setStroke];
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1);
[[UIBezierPath bezierPathWithOvalInRect:CGRectInset(self.bounds, 4, 4)] stroke];
}
@end
@interface BCShapeView : UIView
@end
@implementation BCShapeView
+ (Class)layerClass
{
return [CAShapeLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
self.backgroundColor = nil;
CAShapeLayer *layer = (id)self.layer;
layer.lineWidth = 1;
layer.fillColor = NULL;
layer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(self.bounds, 4, 4)].CGPath;
layer.strokeColor = [UIColor redColor].CGColor;
layer.contentsScale = [UIScreen mainScreen].scale;
layer.shouldRasterize = NO;
}
return self;
}
@end
@implementation BCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *borderView = [[UIView alloc] initWithFrame:CGRectMake(24, 104, 36, 36)];
borderView.layer.borderColor = [UIColor redColor].CGColor;
borderView.layer.borderWidth = 1;
borderView.layer.cornerRadius = 18;
[self.view addSubview:borderView];
BCDrawingView *drawingView = [[BCDrawingView alloc] initWithFrame:CGRectMake(20, 40, 44, 44)];
[self.view addSubview:drawingView];
BCShapeView *shapeView = [[BCShapeView alloc] initWithFrame:CGRectMake(20, 160, 44, 44)];
[self.view addSubview:shapeView];
UILabel *borderLabel = [UILabel new];
borderLabel.text = @"CALayer borderRadius";
[borderLabel sizeToFit];
borderLabel.center = CGPointMake(borderView.center.x + 26 + borderLabel.bounds.size.width/2.0, borderView.center.y);
[self.view addSubview:borderLabel];
UILabel *drawingLabel = [UILabel new];
drawingLabel.text = @"drawRect: UIBezierPath";
[drawingLabel sizeToFit];
drawingLabel.center = CGPointMake(drawingView.center.x + 26 + drawingLabel.bounds.size.width/2.0, drawingView.center.y);
[self.view addSubview:drawingLabel];
UILabel *shapeLabel = [UILabel new];
shapeLabel.text = @"CAShapeLayer UIBezierPath";
[shapeLabel sizeToFit];
shapeLabel.center = CGPointMake(shapeView.center.x + 26 + shapeLabel.bounds.size.width/2.0, shapeView.center.y);
[self.view addSubview:shapeLabel];
}
@end
BEARBEITEN: Für diejenigen, die den Unterschied nicht sehen können, habe ich Kreise übereinander gezeichnet und vergrößert:
Hier habe ich einen roten Kreis mit drawRect:
gezeichnet und dann einen identischen Kreis mit drawRect:
wieder grün darüber gezeichnet . Beachten Sie das begrenzte Ausbluten von Rot. Beide Kreise sind "glatt" (und identisch mit der cornerRadius
Implementierung):
In diesem zweiten Beispiel sehen Sie das Problem. Ich habe einmal mit einem CAShapeLayer
in rot gezeichnet und wieder oben mit einer drawRect:
Implementierung des gleichen Pfades, aber in grün. Beachten Sie, dass Sie viel mehr Inkonsistenzen mit mehr Blutungen aus dem roten Kreis darunter sehen können. Es wird eindeutig anders (und schlimmer) gezeichnet.