特定のフォントのテキスト文字列の幅とフォントサイズを計算するにはどうすればよいですか?


82

いくつかの文字を表示するUILabelがあります。「x」、「y」、「rpm」のように。ラベルのテキストの幅を計算するにはどうすればよいですか(使用可能なスペース全体を使用するわけではありません)。これは自動レイアウト用であり、UILabelの内部に小さいテキストがある場合、別のビューのフレームの長方形が大きくなります。UIFontとフォントサイズが指定されているときにテキストの幅を計算する方法はありますか?また、改行はなく、1行だけです。


どのフォントタイプでもこれをどのように行うかはわかりませんが、固定幅フォントを使用している場合は、文字数を使用して計算できます。公式は完全にはわかりません。
jgallant 2009

回答:


74

NSString UIKitAdditionsのさまざまなsizeWithFont:メソッドを介して正確にそれを行うことができます。あなたの場合、最も単純なバリアントで十分です(複数行のラベルがないため):

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

この方法にはいくつかのバリエーションがあります。改行モードまたは最大サイズを検討する人もいます。


1
UIFontではありません* yourFont = // [UIFont ...]; でも?
PinkFloydRocks 2013

11
「sizeWithFont:」は非推奨です。wcochranによる回答はマークされたものでなければなりません。
Ferran Maylinch 2014年

4
緑色のチェックマークがあるので、sizeWithAttributesを使用するように回答を変更する必要があります。
グレンハウズ2016年

80

sizeWithFontは非推奨になっているので、Swift4とを使用するための元の回答を更新します。.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)
}

サイズは、「YourTextHere」の画面上のサイズ(ポイント単位)である必要があります。


このソリューションを投稿していただきありがとうございます。私はあなたの答えに基づいて拡張機能を書きました。以下に掲載されています。
エイドリアン

swift 4の対応する機能は何ですか?
Swayambhu 2017

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関数を使用してその値を最も近い整数に上げる必要があります。
アレン

55

2019年9月の更新

この答えは、新しい構文を使用してそれを行うためのはるかにクリーンな方法です。

元の回答

基づいて、グレン・ハウズ優秀な答えは、私は、文字列の幅を計算するために拡張機能を作成しました。の幅を設定するようなことをしている場合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
スイフト4の解決策は何ですか?
Swayambhu 2017

1
サイズ(CGSize)を返す関数が1つだけではないのはなぜですか?なぜ2回作業するのですか?
wcochran

@wcochran更新。素晴らしい電話です。
エイドリアン

1
方法はわかりませんが、サイズが正しくありません。
最大

気にしないでください。これは機能しますが、私のテストでは、テキストが切り捨てられないように、少なくとも15のパディングを追加する必要があります。
最大

33

Swift-5

組み込みコンテンツサイズを使用して、テキストの高さと幅を見つけます。

yourLabel.intrinsicContentSize.width

これは、「TEXT」のように文字列間にカスタム間隔がある場合でも機能します


28

Swift4.2のワンライナー🔸

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.