15

UILabel我有一条要启用缩放的多线。

我用 a 嵌入它UIScrollView并将最小缩放设置为 .25 并将最大缩放设置为 4。这很好用,但是我UILabel的字体在除 1 之外的任何缩放级别上看起来都相当粗糙。

我可以处理这个方法:

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

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

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

重要的是,用户当前在文本中滚动的位置不会丢失。

(要了解我的目标,请注意在 Mobile Safari 中,当您缩放文本时,文本会在一瞬间缩放/抗锯齿,然后它会清除以在您当前的缩放比例下很好地呈现)

4

8 回答 8

18

UIScrollView 的内置缩放仅将转换应用于您的内容视图,这会导致缩放因子超过 1.0 时出现模糊。要获得真正清晰的渲染,您需要自己处理缩放。我在这个答案中描述了大部分过程。

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

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

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

于 2010-01-02T15:53:27.100 回答
8

感谢 valvoline 和 Scrimmers 的回答。我的解决方案是你的混合。

子类 UILabel 像这样:

UILabelZoomable.h

+ (Class) layerClass;

UILabelZoomable.m

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

现在,当您在应用程序中使用您喜欢的新 UILabelZoomable 时,请记住这样做:

你的视图控制器.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));
     }];
于 2012-06-15T07:52:36.020 回答
8

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。

于 2012-11-02T15:09:50.543 回答
4

这是我想出的东西:

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

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

于 2015-12-04T09:11:19.240 回答
3

我通过使用这样的覆盖方法将 UILabel 子类化为DetailedUILabel 来实现 Scrimmers 的解决方案;

导入石英核心

#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];
}
于 2014-01-02T18:10:18.747 回答
2

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

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

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

于 2011-07-11T09:17:30.137 回答
2

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

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

于 2012-08-30T08:18:04.383 回答
1

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

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

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

任务完成

于 2011-03-17T16:33:39.427 回答