Jak obliczyć szerokość linii tekstu określonej czcionki i rozmiar czcionki?


Mam UILabel, który wyświetla kilka znaków. Na przykład „x”, „y” lub „rpm”. Jak obliczyć szerokość tekstu na etykiecie (nie zajmuje całego dostępnego miejsca)? To jest dla automatycznego układu, gdzie drugi widok będzie miał większy prostokąt ramki, jeśli jest mniej tekstu w tym UILabel. Czy istnieją metody obliczania tej szerokości tekstu, gdy określono UIFont i rozmiar czcionki? Nie ma również podziału wiersza i jest tylko jedna linia.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ponieważ
sizeWithFont
jest przestarzałe, po prostu zaktualizuję moją pierwotną odpowiedź, aby używała Swift 4 i
.size
//: Playground - noun: a place where people can playimport UIKitif 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)
}

Powinien to być rozmiar ekranu „Twój tekst tutaj” w punktach.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

sizeWithFont:
jest już przestarzałe, zamiast tego użyj
sizeWithAttributes:
:
UIFont *font = [UIFont fontWithName:@"Helvetica" size:30];
NSDictionary *userAttributes = @{NSFontAttributeName: font,
NSForegroundColorAttributeName: [UIColor blackColor]};
NSString *text = @"hello";...
const CGSize textSize = [text sizeWithAttributes: userAttributes];
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz to zrobić za pomocą różnych metod
sizeWithFont:
w

wzbogacenie
http://developer.apple.com/lib ... .html
NSString UIKit. W Twoim przypadku wystarczy najprostsza opcja (ponieważ nie masz etykiet wieloliniowych):
NSString *someString = @"Hello World";
UIFont *yourFont =// [UIFont ...]
CGSize stringBoundingBox = [someString sizeWithFont:yourFont];

Istnieje kilka odmian tej metody, na przykład niektóre uwzględniają tryby łamania linii lub maksymalne rozmiary.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Aktualizacja wrzesień 2019
>
Ta odpowiedź
https://stackoverflow.com/a/52378302/4475605
jest dużo czystszym sposobem na zrobienie tego z nową składnią.

Oryginalna odpowiedź.
>
Oparte na

Doskonała odpowiedź Glen House
https://stackoverflow.com/a/1324429/4475605, Stworzyłem rozszerzenie do obliczania szerokości linii. Jeśli robisz coś takiego, jak ustawienie szerokości
UISegmentedControl
, może to ustawić szerokość na podstawie paska tytułu segmentu.
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)
}
}

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

Anonimowy użytkownik

Potwierdzenie od:


[b]
Swift-5

[/b]>
Użyj intrinsicContentSize, aby znaleźć wysokość i szerokość tekstu.
yourLabel.intrinsicContentSize.width
Będzie działać, nawet jeśli masz interwał użytkownika między liniami typu

"T E X T"
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Pojawiające się w Swift 4.2
>
let size = text.size(withAttributes:[.font: UIFont.systemFont(ofSize:18.0)])
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To proste rozszerzenie działa dobrze w Swift.
extension String {
func size(OfFont font: UIFont) -> CGSize {
return (self as NSString).size(attributes: [NSFontAttributeName: font])
}
}

Za pomocą:
let string = "hello world!"
let font = UIFont.systemFont(ofSize: 12)
let width = string.size(OfFont: font).width// size: {w: 98.912 h: 14.32}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Swift 4
extension String {
func SizeOf(_ font: UIFont) -> CGSize {
return self.size(withAttributes: [NSAttributedStringKey.font: font])
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To jest dla szybkiej wersji 2.3. Możesz uzyskać szerokość linii.
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)
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Nie jestem pewien, jak wydajna jest, ale napisałem tę funkcję, która zwraca rozmiar punktu, który będzie pasował do ciągu o określonej szerokości:
<pre class="lang-swift prettyprint-override">
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
}

I będzie używany w ten sposób:
textView.font = textView.font!.withSize(textView.text!.fontSizeThatFits(targetWidth: view.frame.width, maxFontSize: 50, font: textView.font!))
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli walczysz o zdobycie

szerokość

Tekst S.

obsługa wielu linii

możesz użyć następującego kodu (

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

W ten sam sposób możesz znaleźć wysokość tekstu, jeśli jej potrzebujesz (po prostu przełącz implementację constraintBox):
let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude)

Lub tu

ujednolicona funkcja

aby uzyskać rozmiar tekstu z obsługą wielu wierszy:
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
}

Za pomocą:
let textSize = labelSize(for: "SomeText", maxWidth: contentView.bounds.width, maxHeight: .greatestFiniteMagnitude)
let textHeight = textSize.height.rounded(.up)
let textWidth = textSize.width.rounded(.up)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Dla

Swift 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;
}
}

Używaj go jak ...
let Str = "ABCDEF"
let Font = UIFont.systemFontOfSize(19.0)
let SizeOfString = Str.SizeOfString(font: Font!)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Mój kod służy do tworzenia rozszerzenia UIFont: (to jest Swift 4.1)
extension UIFont {
public func textWidth(s: String) -> CGFloat
{
return s.size(withAttributes: [NSAttributedString.Key.font: self]).width
}}// extension UIFont

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się