CATextLayer如何调整字体大小以适应框架大小

9

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

我需要调整字体大小,以使文本适合框架(而不是相反):)

有什么想法从哪里开始? :)

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


当你说“未知长度的文本”时,是指在编译时不知道吗? 在某些时候,您必须知道文本的长度... - nall
哈哈 - 好的,说得好。这是用户在某个时候输入的文本。当然,我可以获取字符串长度... :) - Swissdude
4个回答

9
工作于 Swift 5 的清晰解决方案。
1)扩展字符串。
extension String {
    func size(OfFont font: UIFont) -> CGSize {
        return (self as NSString).size(withAttributes: [NSAttributedString.Key.font: font])
    }
}

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) 现在转到您的代码,不要使用CATextLayer,而是使用DynamicTextLayer。
textLayer = DynamicTextLayer()
textLayer?.alignmentMode = .center
textLayer?.fontSize = 40
textLayer?.string = "Example"
textLayer?.adjustsFontSizeToFitWidth = true

对我来说,高度多了一些,宽度是完美的。 - Nick
@Nick 你可以像这样获取你正在使用的字体所需的高度 let textLayer = CATextLayer() textLayer.font?.lineHeight - Nick
但是我想在创建CATextLayer之前设置高度。我正在使用CGRect初始化框架。 - Nick
如果您知道将要使用的字体,可以在创建文本层之前计算其高度。 let font = UIFont() font.lineHeight - Nick

6
我通过以下方式实现了它:
    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];

“MaximunWidth”是CALayer的宽度框架吗? - Ofir Malachi
@OfirMalachi 不,它是固定大小,文本大小不能超过它。 - Ricardo Ruiz Romero

1
我最终做了这个: < p > < code > textlayer 是一个 < code > CATextlayer < p > < code > theString 是一个 < code > NSMutableAttributedString 是的,这不是很优雅,肯定可以改进 ;)
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;
    }

2
"defs" 是什么意思? - Bad_Developer

-3
CATextLayer *textLayer;

[textLayer setWrapped: TRUE];

希望这会起作用


哇 - 这看起来非常短... ;) 我会尝试一下! 谢谢! - Swissdude

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接