xcode CATextlayer 更改 FONT 的大小以适合框架

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11059061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:37:15  来源:igfitidea点击:

CATextlayer change size of FONT to fit the frame

iosxcodecatextlayer

提问by Swissdude

I have a CATextlayerof a certain size and NSAttributedStringtext of unknown length.

我有一个CATextlayer特定大小和NSAttributedString未知长度的文本。

I need to adjust the font-size so the text fits the frame (not vice versa :)

我需要调整字体大小,使文本适合框架(反之亦然:)

Any ideas where to start? :)

任何想法从哪里开始?:)

[Edit] as nall points out, I can determine the string length, of course, it's some text entered by the user that I need to fit into a box of fixed size.

[编辑] 正如 nall 指出的那样,我可以确定字符串长度,当然,这是用户输入的一些文本,我需要适合固定大小的框。

采纳答案by Swissdude

I ended up doing this:

我最终这样做了:

textlayeris a CATextlayer

textlayer是一个 CATextlayer

theStringis a NSMutableAttributedString

theString是一个 NSMutableAttributedString

And yes, it's not very elegant and could definitely be improved ;)

是的,它不是很优雅,绝对可以改进;)

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)theString);

    CGRect columnRect = CGRectMake(0, 0 , 320, 150);

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, columnRect);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

    CFRange frameRange = CTFrameGetVisibleStringRange(frame); 

    int fontSize = 18;

    while(theString.string.length > frameRange.length){

        fontSize--;

        CFStringRef fontName = (__bridge CFStringRef)[defs objectForKey:@"font"];

        CTFontRef font = CTFontCreateWithName(fontName, fontSize, NULL);

        [theString addAttribute:(NSString *)kCTFontAttributeName
                          value:(__bridge id)font
                          range:NSMakeRange(0, theString.string.length)];

        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)theString);

        CGRect columnRect = CGRectMake(0, 0 , 320, 150);

        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, NULL, columnRect);

        CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

        frameRange = CTFrameGetVisibleStringRange(frame); 

        textLayer.string = theString;
    }

回答by Ricardo Ruiz Romero

I achieved it by doing this:

我通过这样做实现了它:

    float fontSize = InitialFontSize;
    UIFont *myFont = [UIFont boldSystemFontOfSize:fontSize];
    CGSize myFontSize = [YourTextHere sizeWithFont:myFont];
    while (myFontSize.width >= MaximunWidth) {
        fontSize -= 0.1f;
        myFont = [UIFont boldSystemFontOfSize:fontSize];
        myFontSize = [YourTextHere sizeWithFont:myFont];
    }
    CATextLayer *textLayer = [CATextLayer layer];
    [textLayer setFrame:CGRectMake(MaximunWidth - myFontSize.width / 2, MaximunHeight - myFontSize.height / 2, myFontSize.width, myFontSize.height)];
    [textLayer setFontSize:fontSize];
    [textLayer setString:YourTextHere];

    [textLayer setAlignmentMode:kCAAlignmentCenter];

回答by Nick

Working for Swift 5clean solution.

Swift 5清洁解决方案工作。

1) Extend String

1) 扩展字符串

extension String {
    func size(OfFont font: UIFont) -> CGSize {
        return (self as NSString).size(withAttributes: [NSAttributedString.Key.font: font])
    }
}

2) Subclass the CATextLayer

2) 继承 CATextLayer

class DynamicTextLayer : CATextLayer {
    var adjustsFontSizeToFitWidth = false

    override func layoutSublayers() {
        super.layoutSublayers()
        if adjustsFontSizeToFitWidth {
            fitToFrame()
        }
    }

    func fitToFrame(){
        // Calculates the string size.
        var stringSize: CGSize  {
            get { return (string as? String)!.size(OfFont: UIFont(name: (font as! UIFont).fontName, size: fontSize)!) }
        }
        // Adds inset from the borders. Optional
        let inset: CGFloat = 2
        // Decreases the font size until criteria met
        while frame.width < stringSize.width + inset {
            fontSize -= 1
        }
    }
}

3) Now go to your code and instead of CATextLayer use DynamicTextLayer

3)现在转到您的代码,而不是 CATextLayer 使用 DynamicTextLayer

textLayer = DynamicTextLayer()
textLayer?.alignmentMode = .center
textLayer?.fontSize = 40
textLayer?.string = "Example"
textLayer?.adjustsFontSizeToFitWidth = true

回答by Ranjeet Singh

CATextLayer *textLayer;

[textLayer setWrapped: TRUE];

This will hopefully will work

这有望奏效