ios - caracteristicas - ipad pro precio
El dibujo de iOS en CALayers drawInContext está pixelado o borroso en la retina (3)
Tengo un UIView
personalizado que dibuja algo en un sobrescrito
- (void)drawRect:(CGRect)rect
Esto funciona bien y da resultados nítidos en las pantallas de retina.
Sin embargo, ahora me gustaría hacer que las propiedades en las que se basa el dibujo sean animables. La creación de propiedades animables parece ser posible solo en CALayer
, así que en lugar de hacer el dibujo en UIView
, creo una subclase CALayer
personalizada y hago el dibujo dentro
- (void) drawInContext:(CGContextRef)ctx
Utilizo prácticamente el mismo código de dibujo en esta función que utilicé en la función drawRect
de la vista UIView
personalizada.
El resultado se ve igual, sin embargo, no es una resolución de retina sino pixelada (píxeles cuadrados grandes)
si pongo
self.contentsScale = [UIScreen mainScreen].scale;
Al comienzo de mi implementación drawInContext
, en lugar de un resultado pixelado, obtengo un resultado borroso (como si el renderizado todavía se realiza en resolución sin retina y luego se escala a la resolución de retina).
¿ CALayers
es la manera correcta de representar rutas de retina nítidas en CALayers
drawInContext
?
Aquí hay algunas capturas de pantalla (la línea azul es parte del dibujo personalizado en cuestión. La parte amarilla es solo una imagen)
Dibujado dentro del dibujo personalizado de UIView:
Dibujado dentro del dibujo personalizado de drawInContext
:
Drawin dentro del drawInContext personalizado de drawInContext
, con la configuración self.contentScale
primero:
Para completar, aquí está (una versión simplificada del) código de dibujo:
//if drawing inside custom UIView sublcass:
- (void)drawRect:(CGRect)rect
{
CGContextRef currenctContext = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextSetLineWidth(currenctContext, _lineWidth);
CGContextSetLineJoin(currenctContext,kCGLineJoinRound);
CGContextMoveToPoint(currenctContext,x1, y1);
CGContextAddLineToPoint(currenctContext,x2, y2);
CGContextStrokePath(currenctContext);
}
//if drawing inside custom CALayer subclass:
- (void) drawInContext:(CGContextRef)ctx {
{
//self.contentsScale = [UIScreen mainScreen].scale;
CGContextRef currenctContext = ctx;
CGContextSetStrokeColorWithColor(currenctContext, [UIColor blackColor].CGColor);
CGContextSetLineWidth(currenctContext, _lineWidth);
CGContextSetLineJoin(currenctContext,kCGLineJoinRound);
CGContextMoveToPoint(currenctContext,x1, y1);
CGContextAddLineToPoint(currenctContext,x2, y2);
CGContextStrokePath(currenctContext);
}
Para reafirmar lo que quiero lograr: quiero lograr la misma representación de retina nítida que en el enfoque UIView
, pero cuando se realiza en CALayer
¿Está utilizando shouldRasterize = YES
en la capa? Intente dibujar en la subclase CALayer pero establezca la escala de rasterizationScale
en la escala de la pantalla.
Después de agregarle capa a su super capa. establezca shouldRasterize a YES, configure contentsScale y resterizatioinScale a la escala de pantalla:
[self.progressView.layer addSublayer:self.progressLayer];
self.progressLayer.shouldRasterize = YES;
self.progressLayer.contentsScale = kScreenScale;
self.progressLayer.rasterizationScale = kScreenScale;
CABasicAnimation *animate = [CABasicAnimation animationWithKeyPath:@"progress"];// progress is a customized property of progressLayer
animate.duration = 1.5;
animate.beginTime = 0;
animate.fromValue = @0;
animate.toValue = @1;
animate.fillMode = kCAFillModeForwards;
animate.removedOnCompletion = NO;
animate.repeatCount = HUGE_VALF;
[self.progressLayer addAnimation:animate forKey:@"progressAnimation"];
El problema es más probable que sea contentScale aquí; tenga en cuenta que si está asignando esto a una vista personalizada anulando su función layerClass
, la escala de contenido de la capa puede restablecerse. Puede haber algunos otros casos en los que esto también suceda. Para estar seguro, configure la escala de contenido solo después de que la capa se haya agregado a una vista.
Intente asignar la escala de la pantalla principal a su capa personalizada durante el método de inicio de su vista personalizada. En Swift 3 que se ve así:
layer.contentsScale = UIScreen.mainScreen().scale
O, en Swift 4:
layer.contentsScale = UIScreen.main.scale