2011-07-18 19 views
19

Estoy dibujando un gráfico en un CALayer en su método delegado drawLayer:inContext:.iOS: ¿Cómo soporto Retina Display con CGLayer?

Ahora quiero admitir Retina Display, ya que el gráfico se ve borroso en los últimos dispositivos.

Para las partes que dibujo directamente en el contexto gráfico pasado por el CALayer, puedo dibujar muy bien en alta resolución configurando la propiedad contentScale de CALayer de la siguiente manera.

if ([myLayer respondsToSelector:@selector(setContentsScale:)]) { 
    myLayer.contentsScale = [[UIScreen mainScreen] scale]; 
} 

Pero las partes que utilizo CGLayer todavía se dibujan borrosas.

¿Cómo dibujo un CGLayer en alta resolución para que admita Retina Display?

Quiero usar CGLayer para dibujar las mismas formas de gráfico del gráfico repetidamente, así como para cortar las líneas del gráfico que exceden el borde de la capa.

me sale CGLayer por CGLayerCreateWithContex con el contexto gráfico pasado de la CALayer, y se basan en su contexto usando funciones CG como CGContextFillPath o CGContextAddLineToPoint.

Necesito admitir iOS 4.xy iOS 3.1.3, tanto Retina como visualización heredada.

Gracias,

Kura

+1

Parece que esta publicación puede ser relevante: http://stackoverflow.com/questions/3896968/how-do-i-adjust-a-quartz-2d-context-to-account-for-a-retina -display –

+0

Duncan, gracias por su comentario, pero no ... He leído esta publicación antes, pero esto se trata de dibujar directamente en el contexto de UIView. CALayer tiene la misma 'escala 'de propiedad que UIView y funcionó como lo dije anteriormente. Mi problema está en dibujar en CGLayer. CGLayer no tiene la propiedad 'scale'. :( – Taka

Respuesta

27

Así es como se dibuja un CGLayer correctamente para todas las resoluciones.

  1. La primera vez que la creación de la capa, es necesario calcular los límites correctos multiplicando las dimensiones de la escala:

    int width = 25; 
    int height = 25; 
    float scale = [self contentScaleFactor]; 
    CGRect bounds = CGRectMake(0, 0, width * scale, height * scale); 
    CGLayer layer = CGLayerCreateWithContext(context, bounds.size, NULL); 
    CGContextRef layerContext = CGLayerGetContext(layer); 
    
  2. A continuación, deberá establecer la escala correcta para el contexto de capa:

    CGContextScaleCTM(layerContext, scale, scale); 
    
  3. Si el dispositivo actual tiene una pantalla retina, todos los dibujos realizados en la capa se dibujarán ahora el doble.

  4. Cuando finalmente dibuja el contenido de la capa, asegúrese de usar CGContextDrawLayerInRect y suministro del CGRect sin escala:

    CGRect bounds = CGRectMake(0, 0, width, height); 
    CGContextDrawLayerInRect(context, bounds, layerContext); 
    

eso es todo!

+0

¡Gracias! Lo intentaré la próxima vez;;) – Taka

+0

Gracias , esto es exactamente cómo debe ir. – neevek

+0

Esto mejora la nitidez de manera significativa, pero aún se ve un poco menos nítida que el dibujo directamente con el contexto (no usa 'CGlayer'). ¿Esto es normal? También intenté establecer la escala en 4 u 8. – Ixx

1

yo decidimos no utilizar CGLayer y directamente dibujar en el contexto gráfico de la CALayer, y ahora se dibuja muy bien en alta resolución en la pantalla de la retina.

Encontré la pregunta similar here, y encontré que no tiene sentido usar CGLayer en mi caso.

Utilicé CGLayer debido al programa de ejemplo de Apple "Using Multiple CGLayer Objects to Draw a Flag" que se encuentra en la guía de programación 2D de Quartz. En este ejemplo, crea un CGLayer para una estrella y lo usa varias veces para dibujar 50 estrellas. Pensé que esto era por una razón de rendimiento, pero no vi ninguna diferencia de rendimiento.

Con el fin de cortar las líneas del gráfico que exceden el borde de la capa, decidí usar múltiples CALayers.

+0

Esto no es realmente una solución al problema. Es una pregunta interesante y me gustaría que hubiera una respuesta. El enlace tampoco ofrece una solución que no sea un consejo que contradice los documentos de Apple. –

+1

En cuanto al rendimiento: En mi aplicación estoy usando el método 'UIImage'' drawInRect: '. En uno de los escenarios que he estado midiendo, usar' CGLayer' es aproximadamente 20 veces más rápido que dibujar directamente con el contexto 'CALayer' (~ 50 ms vs. ~ 1 segundo). Así que supongo que probablemente depende del tipo de operaciones de dibujo almacenadas en el 'CGLayer' si hay o no una diferencia de rendimiento. – herzbube

Cuestiones relacionadas