放大UILabel&以正确的大小重新渲染字体

时间:2010-01-02 02:58:12

标签: iphone uiscrollview uilabel

我想要启用放大的多行UILabel

我用UIScrollView嵌入它并将最小缩放设置为.25,最大缩放设置为4.这很有效,但是UILabel的字体看起来相当粗糙,除了1以外的任何缩放级别

我可以处理这个方法:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale

为了将我的UILabel的字体重新调整为更大的尺寸,但视图仍然放大,所以它看起来总是很糟糕。

有没有办法让标签的文字重新渲染一个我完成缩放?

用户当前在文本中滚动的位置非常重要。

(为了了解我的目标,请注意在移动浏览器中缩放文本时如何缩放/消除锯齿一瞬间然后它会清除以在当前缩放比例下渲染得很好)< / p>

8 个答案:

答案 0 :(得分:16)

UIScrollView的内置缩放仅将变换应用于内容视图,这会导致比例因子1.0以上的任何变化模糊。对于真正清晰的渲染,您需要自己处理缩放。我在this answer中描述了一大块过程。

您需要手动跟踪内容视图的比例因子,然后在-scrollViewDidEndZooming:withView:atScale:委托方法中,您将应用该比例。对于你的UILabel,这意味着要改变字体大小以反映新的比例。

为了保持正确的滚动位置,您需要在上面的委托方法中获取UIScrollView的contentOffset,并计算新缩放的UILabel中对应的位置。然后设置滚动视图的contentSize以匹配UILabel的新大小,并使用-setContentOffset:animated:设置新计算的内容偏移量(动画设置为NO)。

正确地计算数学有点棘手,但我在我的一个应用程序中缩放文本时会这样做,这可以在video demonstration of that application中看到(大约1/3标记)。

答案 1 :(得分:8)

感谢valvoline&amp; 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));
     }];

答案 2 :(得分:7)

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。

答案 3 :(得分:3)

我实现了Scrimmers的解决方案,将UILabel作为DetailedUILabel继承,并使用这样的重写方法;

导入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;
}

和layerClass,类方法。

+ (Class)layerClass {
    return [CATiledLayer class];
}

答案 4 :(得分:3)

以下是我提出的问题:

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))
}

还要记住标签应该足够大以显示整个文本。它有时需要一点点重绘,但这种方法相当简单。

答案 5 :(得分:2)

使用CATiledLayer替换CALayer的正确方法如下:

+ (Class)layerClass {
    return [CATiledLayer class]; 
}

除此之外,你必须设置你的偏见细节以及你需要的任何东西。

答案 6 :(得分:2)

我在iOS 5.1和6 beta中测试了JEzu的代码,它适用于const文本标签,但导致其他正常标签需要更新文本内容失败,即文本未更改...

我使用JEzu的答案将UILabel子类化为ZoomableLabel,并将该类应用为标签的自定义类,并且它可以正常工作。

答案 7 :(得分:1)

有一种更简单的方法可以做到这一点..

用CATiledLayer替换UILabel的layerClass并适当设置细节级别。

+ (Class)layerClass
{
    CATiledLayer *layerForView = (CATiledLayer *)self.layer;
    layerForView.levelsOfDetailBias = 2;
    layerForView.levelsOfDetail = 2;
    return [CATiledLayer class];
}

完成工作