Iphone 缩放标签&;以正确的大小重新呈现字体

Iphone 缩放标签&;以正确的大小重新呈现字体,iphone,uiscrollview,uilabel,Iphone,Uiscrollview,Uilabel,我有一个多行ui标签,我想启用缩放功能 我将它嵌入了一个UIScrollView,并将最小缩放设置为.25,最大缩放设置为4。这很好,但是myUILabel的字体在除1以外的任何缩放级别上看起来都相当粗糙 我可以处理这种方法: - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale 为了将UILabel的字体重新调整为更大的字体,但视图仍在放大

我有一个多行
ui标签
,我想启用缩放功能

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

我可以处理这种方法:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
为了将UILabel的字体重新调整为更大的字体,但视图仍在放大,因此看起来总是很糟糕

缩放完成后,有没有办法使标签的文本重新呈现

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


(要了解我的意图,请注意,在Mobile Safari中,当您缩放文本时,文本会在瞬间缩放/消除锯齿,然后它会清除,以在当前缩放比例下渲染良好)

UIScrollView的内置缩放功能仅对内容视图应用变换,这会导致比例因子大于1.0时出现模糊。对于真正的锐利渲染,您需要自己处理缩放。我在中描述了这一过程的一部分

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

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


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

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

将UILabel的layerClass替换为CATiledLayer,并适当设置详细程度

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

完成作业

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

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

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

感谢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>

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

我使用JEzu的答案将UILabel子类化为ZoomableLabel,并将该类应用为标签的自定义类,它运行良好。

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。

我通过将UILabel子类化为DetailedUILabel,并使用如下重写方法实现Scrimmers的解决方案

进口石英砂

#import <QuartzCore/QuartzCore.h>
和layerClass,类方法

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

以下是我想到的:

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

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

感谢您提供的详细答案。这是否意味着我需要放弃scrollview的内置缩放功能?或者当我完成缩放后,我只是以新的比例因子重新渲染曲面?这对最小/最大缩放设置有什么影响?在按住手势时使用内置缩放,然后在手势完成时重新渲染。这是获得良好缩放性能的唯一方法。UIScrollView跟踪整体缩放比例(这就是为什么您需要覆盖内容视图上的变换访问器以抵消此影响),因此它仍将观察最小/最大缩放设置。开始了解更多信息。因此,如果缩放到150%,我可以将标签的字体大小更改为1.5*currentFontSize,重新计算它们的精确滚动位置,然后重新渲染标签。然后我将缩放重置为1并重新计算最小/最大值?我有这个权利吗?这是令人惊讶的好东西,显然你是唯一一个发表过关于这方面的文章的人(这里是SO:)@Yar-很高兴这是有用的。您可能想查看我添加到链接答案中的更新,因为iPhone OS 3.2+中的某些缩放行为发生了更改。太棒了!这是最简单的解决方案,但对我不起作用。缩放后标签仍然模糊。最后一行是怎么回事?CGAffineTransformMakeRotation(1)将标签旋转1弧度。这是我解决此问题的首选方法,但您不需要仿射旋转变换(
CGAffineTransform(rotationAngle:0)
)。
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))
    }
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))
}