2011-01-19 14 views
44

He creado una vista de documento que muestra el número de página en la esquina. El número de página es un uilabel con un color de fondo semitransparente y tiene un radio de esquina (usando la propiedad cornerRadius del view 's layer). He colocado esto encima de UIScrollView. Sin embargo, esto hace que el desplazamiento sea espasmódico. Si elimino el cornerRadius, el rendimiento es bueno. ¿Hay algo que pueda hacer al respecto? ¿Cuál sería una mejor solución? Parece que se ha logrado en el UIWebView sin ningún problema de rendimiento.UILabel layer cornerRadius tiene un impacto negativo en el rendimiento

Respuesta

142

Para las etiquetas, o puntos de vista con las esquinas redondeadas y o colores de fondo y sombras sobre el desplazamiento ve la solución es bastante simple:

El mayor problema es la opción de capa masksToBounds. Esto parece afectar significativamente el rendimiento del impuesto, sin embargo, la etiqueta parece necesitar este ENCENDIDO para enmascarar el color de fondo en las esquinas redondeadas. Para evitar esto, necesita establecer el color de fondo de la capa de etiquetas en su lugar y desactivar masksToBounds.

El segundo problema es que el comportamiento predeterminado es volver a dibujar la vista siempre que sea posible, lo que es totalmente innecesario con elementos estáticos o de cambio lento en las vistas de desplazamiento. Aquí simplemente establecemos layer.shouldRasterize = YES. Esto permitirá que CA "almacene en caché" una versión rasterizada de la vista para un dibujo rápido al desplazarse (presumiblemente con aceleración de hardware).

Debe asegurarse de que su capa tenga un canal alfa, de lo contrario la rasterización afectará el dibujo de las esquinas redondeadas. Nunca he tenido un problema ya que tengo un conjunto alfa para mis colores de fondo, pero es posible que deba verificar su situación.

Aquí está una muestra de UILabel configurar para trabajar muy bien en un scollview:

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(4, 4, 40.0, 24.0)]; 
lbl.font = [UIFont fontWithName:@"Helvetica" size:14.0]; 
lbl.textAlignment = UITextAlignmentRight; 
lbl.text = @"Hello World"; 
// Must set the label background to clear so the layer background shows 
lbl.backgroundColor = [UIColor clearColor];   
// Set UILabel.layer.backgroundColor not UILabel.backgroundColor otherwise the background is not masked to the rounded border. 
lbl.layer.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5].CGColor; 

lbl.layer.cornerRadius = 8; 
lbl.layer.borderColor = [UIColor blackColor].CGColor; 
lbl.layer.borderWidth = 1; 
// Huge change in performance by explicitly setting the below (even though default is supposedly NO) 
lbl.layer.masksToBounds = NO; 
// Performance improvement here depends on the size of your view 
lbl.layer.shouldRasterize = YES; 
lbl.layer.rasterizationScale = [UIScreen mainScreen].scale; 
// self here is the child view in the scroll view 
[self addSubview:lbl]; 
[lbl release]; 

puedo llenar la pantalla del iPad 1 con vistas como esta y todavía desplazarse sin problemas :)

+0

¡Gracias, esto me ayudó a resolver algunos problemas de rendimiento con uitextfields con esquinas redondeadas! – ChristophK

+1

Gracias. Funciona muy bien para mí también. – JHos

+4

BTW si se usa '.shouldRasterize = YES', el contenido de UILabel se ve manchado en los dispositivos retina. – bioffe

3

Tuve un problema similar con UILabel en una personalizada UITableViewCell con esquinas redondeadas. Para obtener un rendimiento sin problemas, hice 'imágenes' con esquinas redondeadas para evitar esto (see).

Muchas otras publicaciones, incluyendo this, o this podrían ayudar.

6

Como sugirió petert, después de ver las publicaciones 'relacionadas' en la barra lateral, decidí crear mi propia imagen. Subclassed UIView y agregué una imagen de fondo (para el fondo con bordes redondeados) y una etiqueta de texto estándar en init. Para crear la imagen de fondo, hago una imagen extensible usando las funciones de dibujo CG.

// create background image 
    CGFloat radius = frame.size.height/2; 
    CGFloat imgSize = (radius*2)+1; // 1 pixel for stretching 
    UIGraphicsBeginImageContext(CGSizeMake(imgSize, imgSize)); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSetAlpha(context, 0.5f); 
    CGContextSetLineWidth(context, 0); 
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); 

    CGFloat minx = 0; 
    CGFloat midx = imgSize/2; 
    CGFloat maxx = imgSize; 
    CGFloat miny = 0; 
    CGFloat midy = imgSize/2; 
    CGFloat maxy = imgSize; 

    CGContextMoveToPoint(context, minx, midy); 
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
    CGContextClosePath(context); 
    CGContextDrawPath(context, kCGPathFillStroke); 

    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    UIImage *stretchImage = [viewImage stretchableImageWithLeftCapWidth:radius topCapHeight:radius]; 

    UIImageView *stretch = [[UIImageView alloc] initWithImage:stretchImage]; 
    stretch.frame = self.bounds; 
    stretch.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth); 
    [self addSubview:stretch]; 
    [self sendSubviewToBack:stretch]; 
    [stretch release]; 
8

me tropecé en este uno también cornerRadius (para UIButton y UIImageView) estaba matando el rendimiento de mi aplicación. No he encontrado ninguna solución de trabajo que redondee UIButton con la imagen de fondo, así que tuve que escribir mi propio código: primer método. Segundo agrega una esquina redonda y un borde a UIImageView. Creo que el código habla por sí mismo.

+(void)setBackgroundImage:(UIImage*)image forButton:(UIButton*)button withCornerRadius:(float)cornerRadius borderColor:(CGColorRef)borderColor andBorderWith:(float)borderWidth 
{ 
    UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:button.frame]; 
    UIGraphicsBeginImageContextWithOptions(tempImageView.bounds.size, NO, 1.0); 
    [[UIBezierPath bezierPathWithRoundedRect:tempImageView.bounds 
           cornerRadius:cornerRadius] addClip]; 
    [image drawInRect:tempImageView.bounds]; 
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    [button setBackgroundImage:tempImageView.image forState:UIControlStateNormal]; 
    button.layer.shouldRasterize = YES; 
    button.layer.borderColor = borderColor; 
    button.layer.borderWidth = borderWidth; 
    button.layer.cornerRadius = cornerRadius; 
} 

+(void)makeRoundedCornersForImageView:(UIImageView*)imgV withCornerRadius:(float)cornerRadius borderColor:(CGColorRef)borderColor andBorderWith:(float)borderWidth 
{ 
    UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:imgV.frame]; 
    UIGraphicsBeginImageContextWithOptions(tempImageView.bounds.size, NO, 1.0); 
    [[UIBezierPath bezierPathWithRoundedRect:tempImageView.bounds 
           cornerRadius:cornerRadius] addClip]; 
    [imgV.image drawInRect:tempImageView.bounds]; 
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    imgV.image = tempImageView.image; 
    imgV.layer.shouldRasterize = YES; 
    imgV.layer.borderColor = borderColor; 
    imgV.layer.borderWidth = borderWidth; 
    imgV.layer.cornerRadius = cornerRadius; 
} 
+0

Muy bien, esto me ayuda. – ZYiOS

+0

ImageView no funciona, la imagen no se recorta. – Blacky

Cuestiones relacionadas