Ios UILabel层半径对性能有负面影响

Ios UILabel层半径对性能有负面影响,ios,uiview,uilabel,calayer,Ios,Uiview,Uilabel,Calayer,我创建了一个文档视图,它在角落中显示页码。页码是一个带有半透明背景色的uilabel,并且有一个角半径(使用视图层的角半径属性)。我已将其放置在UIScrollView上方。然而,这会使滚动不平稳。如果我拆下拐角半径,则性能良好。我能做些什么吗?什么是更好的解决方案?这似乎是在UIWebView中实现的,没有任何性能问题。我在一个圆角自定义UITableViewCell中遇到了类似的UILabel问题。为了获得平滑的性能,我用圆角“制作”了图像来绕过这个() 很多其他帖子,包括,或者可能会有所帮

我创建了一个文档视图,它在角落中显示页码。页码是一个带有半透明背景色的uilabel,并且有一个角半径(使用
视图
角半径
属性)。我已将其放置在
UIScrollView
上方。然而,这会使滚动不平稳。如果我拆下
拐角半径
,则性能良好。我能做些什么吗?什么是更好的解决方案?这似乎是在
UIWebView
中实现的,没有任何性能问题。

我在一个圆角自定义
UITableViewCell
中遇到了类似的
UILabel
问题。为了获得平滑的性能,我用圆角“制作”了图像来绕过这个()


很多其他帖子,包括,或者可能会有所帮助。

就像皮特建议的那样,在看到侧栏中的“相关”帖子后,我决定创建自己的形象。我将UIView子类化,并在init上添加了一个背景图像(用于具有圆形边缘的背景)和一个标准textlabel。为了创建背景图像,我使用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];

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

最大的问题来自masksToBounds层选项。这似乎对性能有很大的影响,但是标签似乎需要这样才能将背景色遮盖到圆角。因此,要解决这个问题,您需要设置标签层背景色,并关闭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];

我可以在iPad1屏幕上显示这样的视图,但仍然可以平滑地滚动:)

我也无意中看到了这个。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;
}

谢谢对我来说也很好。顺便说一句,如果使用
.shouldRasterize=YES
,UILabel的内容在视网膜设备上看起来有污点。@bioffe:这可以通过设置光栅化比例轻松解决:
lbl.layer.rasterizationScale=[UIScreen mainScreen]。比例太完美了!但是UIImageView呢?这太完美了!非常感谢。我认为@DanielRinser关于光栅化比例的评论应该是答案的一部分,因为现在基本上每个设备都是视网膜显示器