특정 글꼴 및 글꼴 크기의 텍스트 문자열 너비를 계산하는 방법은 무엇입니까?


82

일부 문자를 표시하는 UILabel이 있습니다. "x", "y"또는 "rpm"처럼. 레이블의 텍스트 너비를 어떻게 계산할 수 있습니까 (사용 가능한 전체 공간을 사용하지 않음)? 이것은 자동 레이아웃을위한 것으로, UILabel 내부에 더 작은 텍스트가있는 경우 다른 뷰가 더 큰 프레임 사각형을 갖게됩니다. UIFont 및 글꼴 크기가 지정된 경우 텍스트 너비를 계산하는 방법이 있습니까? 줄 바꿈도없고 한 줄만 있습니다.


어떤 글꼴 유형으로도이 작업을 수행 할 수 있을지 모르겠지만 고정 너비 글꼴을 사용하는 경우 문자 수를 사용하여 계산할 수 있습니다. 나는 공식을 완전히 확신하지 못합니다.
jgallant

답변:


73

NSString UIKit Additions 의 다양한 sizeWithFont:메소드 를 통해 정확하게 할 수 있습니다 . 귀하의 경우에는 가장 간단한 변형으로 충분할 것입니다 (여러 줄 레이블이 없기 때문에).

NSString *someString = @"Hello World";
UIFont *yourFont = // [UIFont ...]
CGSize stringBoundingBox = [someString sizeWithFont:yourFont];

이 방법에는 여러 가지 변형이 있습니다. 일부는 줄 바꿈 모드 또는 최대 크기를 고려합니다.


1
UIFont가 아니어야합니다. * yourFont = // [UIFont ...]; 그러나?
PinkFloydRocks 2013

네, 물론 이죠 .. 해결되었습니다.
Daniel Rinser 2013 년

11
"sizeWithFont :"는 더 이상 사용되지 않습니다. wcochran의 답변이 표시된 답변이어야합니다.
Ferran Maylinch 2014 년

4
녹색 확인 표시가 있으므로 sizeWithAttributes를 사용하도록 답변을 변경해야합니다.
Glenn Howes 2016 년

80

이후 sizeWithFont사용되지 않습니다, 난 그냥 스위프트 4 사용하여 내 원래의 대답을 업데이트가는거야.size

//: Playground - noun: a place where people can play

import UIKit

if let font = UIFont(name: "Helvetica", size: 24) {
   let fontAttributes = [NSAttributedStringKey.font: font]
   let myText = "Your Text Here"
   let size = (myText as NSString).size(withAttributes: fontAttributes)
}

크기는 "여기에 텍스트"의 화면 크기 (포인트) 여야합니다.


이 솔루션을 게시 해 주셔서 감사합니다. 귀하의 답변을 바탕으로 확장 기능을 작성했습니다. 아래에 게시되어 있습니다.
Adrian

Swift 4의 해당 기능은 무엇입니까?
Swayambhu

77

sizeWithFont:이제 더 이상 사용되지 않습니다. sizeWithAttributes:대신 사용하십시오.

UIFont *font = [UIFont fontWithName:@"Helvetica" size:30];
NSDictionary *userAttributes = @{NSFontAttributeName: font,
                                 NSForegroundColorAttributeName: [UIColor blackColor]};
NSString *text = @"hello";
...
const CGSize textSize = [text sizeWithAttributes: userAttributes];

8
참고 : sizeWithAttributes:메서드는 분수 크기를 반환합니다. 반환 된 크기를 사용하여 뷰 크기를 조정하려면 ceil 함수를 사용하여 가장 가까운 높은 정수로 값을 높여야합니다.
Allen

55

2019 년 9 월 업데이트

이 답변 은 새로운 구문을 사용하여 훨씬 더 깔끔한 방법입니다.

원래 답변

Glenn Howes의 탁월한 답변을 바탕으로 문자열의 너비를 계산하는 확장을 만들었습니다. 의 너비를 설정하는 것과 같은 작업을 수행하는 경우 UISegmentedControl세그먼트의 제목 문자열을 기반으로 너비를 설정할 수 있습니다.

extension String {

    func widthOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = self.size(withAttributes: fontAttributes)
        return size.width
    }

    func heightOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = self.size(withAttributes: fontAttributes)
        return size.height
    }

    func sizeOfString(usingFont font: UIFont) -> CGSize {
        let fontAttributes = [NSAttributedString.Key.font: font]
        return self.size(withAttributes: fontAttributes)
    }
}

용법:

    // Set width of segmentedControl
    let starString = "⭐️"
    let starWidth = starString.widthOfString(usingFont: UIFont.systemFont(ofSize: 14)) + 16
    segmentedController.setWidth(starWidth, forSegmentAt: 3)

1
Swift 4의 솔루션은 무엇입니까?
Swayambhu

1
크기 (CGSize)를 반환하는 하나의 함수가 아닌 이유는 무엇입니까? 왜 두 번 일합니까?
wcochran

@wcochran 업데이트되었습니다. 좋은 전화.
Adrian

1
방법은 모르겠지만 이로 인해 잘못된 크기가 표시됩니다.
Max

신경 쓰지 마세요. 작동하지만 내 테스트 에서 텍스트가 잘리지 않도록 패딩을 15 개 이상 추가해야합니다 .
Max

33

스위프트 -5

intrinsicContentSize를 사용하여 텍스트 높이와 너비를 찾습니다.

yourLabel.intrinsicContentSize.width

이것은 "TEX T" 와 같이 문자열 사이에 사용자 정의 간격이있는 경우에도 작동합니다.


26

Swift 4.2의 Oneliner 🔸

let size = text.size(withAttributes:[.font: UIFont.systemFont(ofSize:18.0)])

6

Swift의이 간단한 확장은 잘 작동합니다.

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

용법:

let string = "hello world!"
let font = UIFont.systemFont(ofSize: 12)
let width = string.size(OfFont: font).width // size: {w: 98.912 h: 14.32}

3

스위프트 4

extension String {
    func SizeOf(_ font: UIFont) -> CGSize {
        return self.size(withAttributes: [NSAttributedStringKey.font: font])
    }
}

2

이것은 신속한 2.3 버전입니다. 문자열의 너비를 얻을 수 있습니다.

var sizeOfString = CGSize()
if let font = UIFont(name: "Helvetica", size: 14.0)
    {
        let finalDate = "Your Text Here"
        let fontAttributes = [NSFontAttributeName: font] // it says name, but a UIFont works
        sizeOfString = (finalDate as NSString).sizeWithAttributes(fontAttributes)
    }

2

당신은 텍스트 얻기 위해 고군분투하는 경우 여러 지원 당신이 다음 코드 (사용할 수 있도록, 스위프트 5 )

func width(text: String, height: CGFloat) -> CGFloat {
    let attributes: [NSAttributedString.Key: Any] = [
        .font: UIFont.systemFont(ofSize: 17)
    ]
    let attributedText = NSAttributedString(string: text, attributes: attributes)
    let constraintBox = CGSize(width: .greatestFiniteMagnitude, height: height)
    let textWidth = attributedText.boundingRect(with: constraintBox, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).width.rounded(.up)

    return textWidth
}

필요한 경우 동일한 방법으로 텍스트 높이를 찾을 수 있습니다 (constraintBox 구현 만 전환).

let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude)

또는 여러 줄 지원으로 텍스트 크기를 가져 오는 통합 함수 는 다음과 같습니다.

func labelSize(for text: String, maxWidth: CGFloat, maxHeight: CGFloat) -> CGSize {
    let attributes: [NSAttributedString.Key: Any] = [
        .font: UIFont.systemFont(ofSize: 17)
    ]

    let attributedText = NSAttributedString(string: text, attributes: attributes)

    let constraintBox = CGSize(width: maxWidth, height: maxHeight)
    let rect = attributedText.boundingRect(with: constraintBox, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).integral

    return rect.size
}

용법:

let textSize = labelSize(for: "SomeText", maxWidth: contentView.bounds.width, maxHeight: .greatestFiniteMagnitude)
let textHeight = textSize.height.rounded(.up)
let textWidth = textSize.width.rounded(.up)

1

대한 스위프트 3.0 이상

extension String {
    func SizeOf_String( font: UIFont) -> CGSize {
        let fontAttribute = [NSFontAttributeName: font]
        let size = self.size(attributes: fontAttribute)  // for Single Line
       return size;
   }
}

다음과 같이 사용하십시오.

        let Str = "ABCDEF"
        let Font =  UIFont.systemFontOfSize(19.0)
        let SizeOfString = Str.SizeOfString(font: Font!)

1

이것이 얼마나 효율적인지 확실하지 않지만 주어진 너비에 문자열을 맞출 포인트 크기를 반환하는이 함수를 작성했습니다.

func fontSizeThatFits(targetWidth: CGFloat, maxFontSize: CGFloat, font: UIFont) -> CGFloat {
    var variableFont = font.withSize(maxFontSize)
    var currentWidth = self.size(withAttributes: [NSAttributedString.Key.font:variableFont]).width

    while currentWidth > targetWidth {
        variableFont = variableFont.withSize(variableFont.pointSize - 1)
        currentWidth = self.size(withAttributes: [NSAttributedString.Key.font:variableFont]).width
    }

    return variableFont.pointSize
}

그리고 다음과 같이 사용됩니다.

textView.font = textView.font!.withSize(textView.text!.fontSizeThatFits(targetWidth: view.frame.width, maxFontSize: 50, font: textView.font!))


0

내 코드는 UIFont를 확장하는 것입니다. (이것은 Swift 4.1입니다)

extension UIFont {


    public func textWidth(s: String) -> CGFloat
    {
        return s.size(withAttributes: [NSAttributedString.Key.font: self]).width
    }

} // extension UIFont
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.