Tengo un UILabel que muestra algunos caracteres. Como "x", "y" o "rpm". ¿Cómo puedo calcular el ancho del texto en la etiqueta (no ocupa todo el espacio disponible)? Esto es para el diseño automático, donde otra vista tendrá un rectángulo de marco más grande si esa UILabel tiene un texto más pequeño adentro. ¿Existen métodos para calcular ese ancho del texto cuando se especifica un UIFont y un tamaño de fuente? Tampoco hay salto de línea y solo una línea.
82
Respuestas:
Puede hacer exactamente eso a través de los diversos
sizeWithFont:
métodos en NSString UIKit Additions . En su caso, la variante más simple debería ser suficiente (ya que no tiene etiquetas de varias líneas):NSString *someString = @"Hello World"; UIFont *yourFont = // [UIFont ...] CGSize stringBoundingBox = [someString sizeWithFont:yourFont];
Hay varias variaciones de este método, por ejemplo. algunos consideran modos de salto de línea o tamaños máximos.
fuente
Dado que
sizeWithFont
está en desuso, solo actualizaré mi respuesta original para usar Swift 4 y.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) }
El tamaño debe ser el tamaño en pantalla de "Su texto aquí" en puntos.
fuente
sizeWithFont:
ahora está en desuso, usesizeWithAttributes:
en su lugar:UIFont *font = [UIFont fontWithName:@"Helvetica" size:30]; NSDictionary *userAttributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: [UIColor blackColor]}; NSString *text = @"hello"; ... const CGSize textSize = [text sizeWithAttributes: userAttributes];
fuente
sizeWithAttributes:
método devuelve tamaños fraccionarios; para usar un tamaño devuelto para cambiar el tamaño de las vistas, debe aumentar su valor al número entero superior más cercano mediante la función ceil.Actualización de septiembre de 2019
Esta respuesta es una forma mucho más limpia de hacerlo usando una nueva sintaxis.
Respuesta original
Basado en la excelente respuesta de Glenn Howes , creé una extensión para calcular el ancho de una cadena. Si está haciendo algo como establecer el ancho de a
UISegmentedControl
, esto puede establecer el ancho según la cadena del título del segmento.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) } }
uso:
// Set width of segmentedControl let starString = "⭐️" let starWidth = starString.widthOfString(usingFont: UIFont.systemFont(ofSize: 14)) + 16 segmentedController.setWidth(starWidth, forSegmentAt: 3)
fuente
Swift-5
Utilice intrinsicContentSize para encontrar la altura y el ancho del texto.
yourLabel.intrinsicContentSize.width
Esto funcionará incluso si tiene un espacio personalizado entre su cadena como "TEX T"
fuente
Oneliner en Swift 4.2 🔸
let size = text.size(withAttributes:[.font: UIFont.systemFont(ofSize:18.0)])
fuente
Esta simple extensión en Swift funciona bien.
extension String { func size(OfFont font: UIFont) -> CGSize { return (self as NSString).size(attributes: [NSFontAttributeName: font]) } }
Uso:
let string = "hello world!" let font = UIFont.systemFont(ofSize: 12) let width = string.size(OfFont: font).width // size: {w: 98.912 h: 14.32}
fuente
Rápido 4
extension String { func SizeOf(_ font: UIFont) -> CGSize { return self.size(withAttributes: [NSAttributedStringKey.font: font]) } }
fuente
Esto es para la versión rápida 2.3. Puede obtener el ancho de la cuerda.
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) }
fuente
Si tiene dificultades para obtener el ancho del texto con soporte multilínea , entonces puede usar el siguiente código ( 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 }
Y de la misma manera que puede encontrar la altura del texto si lo necesita (simplemente cambie la implementación de la caja de restricción):
let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude)
O aquí hay una función unificada para obtener el tamaño del texto con soporte multilínea:
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 }
Uso:
let textSize = labelSize(for: "SomeText", maxWidth: contentView.bounds.width, maxHeight: .greatestFiniteMagnitude) let textHeight = textSize.height.rounded(.up) let textWidth = textSize.width.rounded(.up)
fuente
Para 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; } }
Úselo como ...
let Str = "ABCDEF" let Font = UIFont.systemFontOfSize(19.0) let SizeOfString = Str.SizeOfString(font: Font!)
fuente
No estoy seguro de cuán eficiente es esto, pero escribí esta función que devuelve el tamaño de punto que se ajustará a una cadena a un ancho determinado:
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 }
Y se usaría así:
textView.font = textView.font!.withSize(textView.text!.fontSizeThatFits(targetWidth: view.frame.width, maxFontSize: 50, font: textView.font!))
fuente
La forma en que lo estoy haciendo mi código es hacer una extensión de UIFont: (Esto es Swift 4.1)
extension UIFont { public func textWidth(s: String) -> CGFloat { return s.size(withAttributes: [NSAttributedString.Key.font: self]).width } } // extension UIFont
fuente