Увеличить шрифт UILabel & Re-render в правильном размере
У меня есть многострочный UILabel
, который я хочу включить масштабирование.
Я вложил его с помощью UIScrollView
и установил минимальное масштабирование до 0,25 и максимальное увеличение до 4. Это хорошо работает, однако мой шрифт UILabel
выглядит довольно грубым при любом уровне масштабирования, отличном от 1.
Я могу обработать этот метод:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
чтобы изменить размер шрифта моего UILabel на нечто большее, но вид все еще увеличивается, поэтому он всегда выглядит ужасно.
Есть ли способ сделать повторный рендеринг текста ярлыка? Я сделал масштабирование?
Важно, чтобы текущая прокрученная позиция в тексте не терялась.
(Чтобы понять, что я собираюсь, обратите внимание на то, как в Mobile Safari при масштабировании текст масштабируется/сглаживается на долю секунды, затем он очищается, чтобы хорошо отображать текущую масштаб масштаба)
Ответы
Ответ 1
Встроенное масштабирование UIScrollView применяет только преобразование к вашему представлению контента, что приводит к размытости при чем-либо, превышающем масштабный коэффициент 1,0. Для действительно четкого рендеринга вам потребуется обработать масштабирование самостоятельно. Я описываю фрагмент процесса в этом ответе.
Вам нужно будет отслеживать масштабный коэффициент представления содержимого вручную, а затем в методе -scrollViewDidEndZooming: withView: atScale: delegate вы примените эту шкалу. Для вашего UILabel это будет означать изменение размера шрифта, чтобы отразить новый масштаб.
Чтобы сохранить правильную позицию прокрутки, вам нужно захватить contentOffset для UIScrollView в указанном выше методе делегата и рассчитать, какая позиция соответствует обновленному UILabel. Затем вы устанавливаете contentSize прокрутки в соответствии с новым размером UILabel и используете -setContentOffset: animated: для установки вновь вычисленного смещения контента (с анимированным набором в НЕТ).
Немного сложно получить математику правильно, но я делаю это при масштабировании текста в одном из моих приложений, что можно увидеть в демонстрации этой заявки (примерно на отметке 1/3).
Ответ 2
Спасибо valvoline и Scrimmers за ваши ответы. Мое решение было комбинацией между вашими.
Подкласс UILabel выглядит следующим образом:
UILabelZoomable.h
+ (Class) layerClass;
UILabelZoomable.m
+ (Class) layerClass
{
return [CATiledLayer class];
}
Теперь, когда вы используете свой новый UILabelZoomable в своем приложении, не забудьте сделать это:
YourViewController.m
CATiledLayer *tiledLayer = (CATiledLayer*)textoLabel.layer;
tiledLayer.levelsOfDetail = 10;
tiledLayer.levelsOfDetailBias = 10;
Не забудьте добавить структуру QuartzCore!
#import <QuartzCore/QuartzCore.h>
Наслаждайтесь резким и красивым визуализированным текстом:
[UIView animateWithDuration:1 animations:^
{
yourLabel.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(200, 200), CGAffineTransformMakeRotation(1));
}];
Ответ 3
iOS 4 +
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
scrollView.contentScaleFactor = scale;
for (UIView *subview in scrollView.subviews) {
subview.contentScaleFactor = scale;
}
}
Если это становится слишком интенсивным, а производительность медленная, просто попробуйте установить contentScaleFactor только для своих меток.
Ответ 4
Я реализовал решение Scrimmers, выполнив подклассификацию UILabel как DetailedUILabel с помощью таких переопределяющих методов:
import QuartzCore
#import <QuartzCore/QuartzCore.h>
переопределить метод init, initWithFrame в зависимости от того, что вы хотите.
- (id)init
{
self = [super init];
if (self) {
CATiledLayer *tiledLayer = (CATiledLayer *)self.layer;
tiledLayer.levelsOfDetailBias = 4;
tiledLayer.levelsOfDetail = 4;
self.opaque = YES;
}
return self;
}
и classClass, метод класса.
+ (Class)layerClass {
return [CATiledLayer class];
}
Ответ 5
Правильный способ заменить CALayer на CATiledLayer выглядит следующим образом:
+ (Class)layerClass {
return [CATiledLayer class];
}
вы должны установить свою детализацию и все, что вам нужно.
Ответ 6
Я тестировал код JEzu в iOS 5.1 и 6 beta, он работает для текстовой метки const, но причиной того, что другая нормальная метка требует обновления текстового содержимого, не изменяется, т.е. текст не изменяется...
Я подклассифицирую UILabel как ZoomableLabel с ответом JEzu и применяю класс как пользовательский класс метки, и он отлично работает.
Ответ 7
Вот что я придумал:
func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat) {
label.font = UIFont(name: "YourFont", size: fontSize * scale)
label.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1 / scale, 1 / scale), CGAffineTransformMakeRotation(0))
}
Обновлено для Swift 4.0:
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
label.font = label.font.withSize(fontSize * scale)
label.transform = CGAffineTransform(scaleX: 1 / scale, y: 1 / scale).concatenating(CGAffineTransform(rotationAngle: 0))
}
А также помните, что ярлык должен быть достаточно большим, чтобы отобразить весь текст. Иногда требуется перерисовать крошечный бит, но этот метод довольно прост.
Ответ 8
Существует более простой способ сделать это.
Замените layerClass UILabel на CATiledLayer и соответствующим образом установите уровень детализации.
+ (Class)layerClass
{
CATiledLayer *layerForView = (CATiledLayer *)self.layer;
layerForView.levelsOfDetailBias = 2;
layerForView.levelsOfDetail = 2;
return [CATiledLayer class];
}
Задание выполнено