Zoom UILabel & Re-render font at correct size

后端 未结 8 2413
情歌与酒
情歌与酒 2020-12-13 07:23

I have a multi-line UILabel that I want to enable zooming on.

I embedded it with a UIScrollView and set min zoom to .25 and max zoom to 4.

相关标签:
8条回答
  • 2020-12-13 07:59

    iOS 4+

    - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
        scrollView.contentScaleFactor = scale;
        for (UIView *subview in scrollView.subviews) {
            subview.contentScaleFactor = scale;
        }
    }
    

    If this gets too intensive and performance is slow, just try setting the contentScaleFactor for only your labels.

    0 讨论(0)
  • 2020-12-13 08:02

    Here is something that I have come up with:

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

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

    And also remember that the label should be large enough to show the whole text. It sometimes takes a tiny bit to redraw, but this method is fairly simple.

    0 讨论(0)
  • 2020-12-13 08:08

    The UIScrollView's built-in scaling only applies a transform to your content view, which results in blurriness at anything above a scale factor of 1.0. For truly sharp rendering, you'll need to handle the scaling yourself. I describe a chunk of the process in this answer.

    You'll need to keep track of the scale factor of the content view manually, then in the -scrollViewDidEndZooming:withView:atScale: delegate method you'll apply that scale. For your UILabel, that will mean changing the font size to reflect the new scale.

    In order to maintain the correct scroll position, you'll need to grab the contentOffset of the UIScrollView within the above delegate method and calculate what position that corresponds to in the newly scaled UILabel. You then set the contentSize of the scroll view to match the new size of the UILabel and use -setContentOffset:animated: to set the newly calculated content offset (with animated set to NO).

    It's a little tricky to get the math right, but I do this when scaling text in one of my applications, which can be seen in the video demonstration of that application (at about the 1/3 mark).

    0 讨论(0)
  • 2020-12-13 08:14

    There is a simpler way to do this..

    Replace the layerClass of the UILabel with a CATiledLayer and set the level of detail appropriately.

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

    Job done

    0 讨论(0)
  • 2020-12-13 08:15

    Thanks valvoline & Scrimmers for your answers. My solution was a mix between yours.

    Subclass UILabel like this:

    UILabelZoomable.h

    + (Class) layerClass;
    

    UILabelZoomable.m

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

    Now, when you use your fancy new UILabelZoomable in your app, remember to do this:

    YourViewController.m

    CATiledLayer *tiledLayer = (CATiledLayer*)textoLabel.layer;
    tiledLayer.levelsOfDetail = 10;
    tiledLayer.levelsOfDetailBias = 10;
    

    Remember to add the QuartzCore framework!

    #import <QuartzCore/QuartzCore.h>
    

    Enjoy sharp and a beautiful rendered text:

    [UIView animateWithDuration:1 animations:^
         {
             yourLabel.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(200, 200), CGAffineTransformMakeRotation(1));
         }];
    
    0 讨论(0)
  • 2020-12-13 08:15

    the correct way to substitute a CALayer with a CATiledLayer is as follow:

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

    apart, you've to set your bias detail and whatever you need.

    0 讨论(0)
提交回复
热议问题