Уровень UILabel cornerRadius отрицательно влияет на производительность
Я создал вид документа, который отображает номер страницы в углу. Номер страницы - это uilabel с полупрозрачным цветом фона и имеет радиус угла (с использованием свойства cornerRadius
view
layer
). Я разместил это выше UIScrollView
. Однако, это делает прокрутку отрывистым. Если я удалю cornerRadius
, производительность будет хорошей. Есть ли что-нибудь, что я могу сделать по этому поводу? Что было бы лучшим решением? Похоже, что это было достигнуто в UIWebView
без каких-либо проблем с производительностью.
Ответы
Ответ 1
Для ярлыков или представлений с закругленными углами или цветами фона и тенями при просмотре прокрутки решение довольно просто:
Самая большая проблема связана с параметром слоя masksToBounds. Это, по-видимому, значительно влияет на налоговую эффективность, однако на этикетке, по-видимому, требуется это ПО, чтобы замаскировать цвет фона в закругленные углы. Поэтому, чтобы обойти это, вам нужно установить цвет фона меток и отключить маски.
Вторая проблема заключается в том, что поведение по умолчанию состоит в том, чтобы по возможности перерисовывать представление, которое совершенно не нужно со статическими или медленно меняющимися элементами при просмотре прокрутки. Здесь мы просто устанавливаем layer.shouldRasterize = YES. Это позволит CA "кэшировать" растрированную версию представления для быстрого рисования при прокрутке (предположительно с аппаратным ускорением).
Вам нужно убедиться, что ваш слой имеет альфа-канал, иначе растеризация будет влиять на рисование округлых углов. У меня никогда не было проблемы, поскольку у меня есть альфа-набор для моих цветов фона, но вам может потребоваться проверить вашу ситуацию.
Вот пример 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 с такими видами и по-прежнему прокручивать гладко:)
Ответ 2
Я тоже наткнулся на это. 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;
}
Ответ 3
Как и предложил Петерт, увидев "связанные" сообщения в боковой панели, я решил создать свой собственный образ. Я подклассифицировал UIView и добавил фоновое изображение (для фона с закругленными краями) и стандартную текстовую метку в init. Чтобы создать фоновое изображение, я делаю растяжимое изображение, используя функции рисования 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];
Ответ 4
У меня была аналогичная проблема с UILabel
в пользовательском UITableViewCell
с закругленными углами. Чтобы добиться плавной производительности, я сделал "изображения с закругленными углами, чтобы обойти это (см.).
Многие другие сообщения, в том числе this, или , могут помочь.