UILabel层cornerRadius对性能造成负面影响

问题描述:

我创建了一个文档视图,它显示了角落中的页码。页码是具有半透明背景颜色的uilabel,并具有角落半径(使用viewcornerRadius的属性layer)。我已将此定位于UIScrollView以上。但是,这会导致滚动干扰。如果我删除cornerRadius,性能很好。我能做些什么吗?什么会是更好的解决方案?这似乎已在UIWebView中实现,没有任何性能问题。UILabel层cornerRadius对性能造成负面影响

对于标签,或视图圆角和或背景颜色和阴影上滚动查看该解决方案是非常简单的:

最大的问题是从masksToBounds层选项。这似乎对性能有很大的影响,但标签似乎需要这个ON来将背景颜色蒙上圆角。所以为了解决这个问题,你需要设置标签图层的背景颜色,然后关掉masksToBounds。

第二个问题是,默认行为是尽可能重绘视图,这对于滚动视图中的静态或缓慢更改项目是完全不必要的。这里我们简单地设置layer.shouldRasterize = YES。这将允许CA'滚动'视图的栅格化版本,以便在滚动时进行快速绘制(推测可能带有硬件加速)。

您需要确保您的图层具有Alpha通道,否则栅格化会影响圆角的绘制。我从来没有遇到过问题,因为我为背景颜色设置了alpha,但您可能需要检查您的情况。

下面是一个简单的UILabel成立于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]; 

我可以填写在iPad 1的屏幕,景色像这样,仍然顺利滚动:)

+0

谢谢,这帮助我解决了带有圆角的uitextfields的一些性能问题! – ChristophK 2011-09-20 14:57:14

+1

谢谢。对我也很好。 – JHos 2012-03-23 01:45:42

我有一个UILabel与圆角自定义UITableViewCell类似的问题。为了获得平稳的表现,我'制作了'具有圆角的图像来解决这个问题(see)。

很多其他职位,包括thisthis可能会帮助。

就像petert建议的那样,在看到侧栏中'相关'的帖子后,我决定创建自己的图片。我subclassed UIView并添加一个背景图像(具有圆角边缘的背景)和一个标准的初始化文本标签。要创建背景图像,我使用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]; 

我一头栽进这个一个也是。 cornerRadius(用于UIButton和UIImageView)正在破坏我的应用性能。我发现没有工作解决方案将UIButton与背景图像进行四舍五入,所以我必须编写自己的一段代码 - 第一种方法。第二个将一个圆角和边框添加到UIImageView。我认为这个代码本身就是有说服力的。

+(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; 
}