2012-08-23 17 views
12

Estoy intentando cambiar el tamaño de un campo/vista de texto automáticamente dependiendo de su ancho actual. En otras palabras, quiero que el ancho permanezca constante, pero cambie el tamaño de la altura de acuerdo con el texto que se le proporciona.NSString boundingRectWithSize subestimando ligeramente la altura correcta, ¿por qué?

Parece que funciona, pero por alguna razón se está alineando en la parte inferior de mi ventana a pesar de los esfuerzos para moverla hacia atrás manualmente. ¿Alguien puede ver lo que estoy haciendo mal aquí?

enter image description here

NSString *temp = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer vel felis nec massa ultricies blandit non id arcu. Sed enim est, facilisis a feugiat in, consectetur eget arcu. Aenean rutrum, lacus id euismod congue, nisl erat vulputate lectus, non faucibus tortor purus sed sem. Donec tempor dui egestas velit auctor vitae faucibus diam facilisis. Morbi convallis nulla quis est pulvinar quis ultricies sem sollicitudin."; 

myText.stringValue = temp; 

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSFont systemFontOfSize:12], NSFontAttributeName, 
          [NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName, 
          nil]; 

NSSize size = NSMakeSize(window.frame.size.width, 200); 
myText.frame = [temp boundingRectWithSize:size options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; 

EDIT: Incluso cuando se mueve manualmente el bastidor está claro que el texto aún se está cortada. El tamaño recién ajustado no está del todo allí. enter image description here

esto es en referencia a: NSString boundingRectWithSize slightly underestimating the correct width - why? y NSTextView or NSTextField automatically resize bounds/frame?

+0

cambiar Quizás altura de 200 a algo mucho más grande para que el marco el tamaño sabe crecer verticalmente – rein

+0

@rein Sigo jugando con eso y, aunque de hecho cambia el tamaño del nuevo fotograma, sigue recortando texto en la parte inferior. El nuevo marco no es lo suficientemente grande. Vea la pregunta actualizada para una nueva captura de pantalla. –

Respuesta

15

Tuve el mismo problema. He encontrado lo siguiente en the Documentation:

Para dibujar correctamente y el tamaño del texto de varias líneas, pase NSStringDrawingUsesLineFragmentOrigin en el parámetro de opciones.

Este método devuelve tamaños fraccionarios (en el componente de tamaño del devuelto CGRect); para usar una vista de tamaño devuelto a tamaño, debe elevar su valor al número entero más alto más cercano utilizando la función ceil.

Así que esto lo resolvió para mí:

CGRect rect = [myLabel.text boundingRectWithSize:CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX) 
                options:NSStringDrawingUsesLineFragmentOrigin 
               attributes:@{NSFontAttributeName: myLabel.font} 
                context:nil]; 
rect.size.width = ceil(rect.size.width); 
rect.size.height = ceil(rect.size.height); 

Update (Swift 3)

Una forma alternativa Swift 3 para hacer esto sería:

let size = myLabel.text!.size(
    attributes: [NSFontAttributeName: myLabel.font] 
) 
let rect = CGSize(
    width: ceil(size.width), 
    height: ceil(size.height) 
) 

Ver this answer para un ejemplo de Objective-C.

+0

Gracias por esto, me ayudó mucho – phyzalis

+2

OR 'con NSLineBreakByWordWrapping no es válido y no funciona para mí de todos modos. No es miembro de la enumeración NSStringDrawingOptions. – iphone007

+0

Hmm .. ¡Tienes razón! ¿Lo intentó con 'NSStringDrawingUsesLineFragmentOrigin'? ¿Funcionó? Yo editaba el fragmento entonces. –

1

Esto es lo que terminé yendo con (al menos por el momento) parece que funciona bien, sin embargo todavía me siento como si hubiera es una mejor manera de lograr esto.

NSString *temp = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer vel felis nec massa ultricies blandit non id arcu. Sed enim est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer vel felis nec massa ultricies blandit non id arcu. Sed enim est."; 

myText.stringValue = temp; 

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSFont systemFontOfSize:12], NSFontAttributeName, 
          [NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName, 
          nil]; 

NSSize size = NSMakeSize(window.frame.size.width, MAXFLOAT); 


myText.frame = [temp boundingRectWithSize:size options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; 

// Keep current width but add some more on the bottom 
NSSize tF = myText.frame.size; 
[myText setFrameSize:NSMakeSize(tF.width, tF.height + 35)]; 

[myText setFrameOrigin:NSMakePoint((NSWidth(window.frame) - NSWidth(myText.frame))/2, 
            (NSHeight(window.frame) - NSHeight(myText.frame) - 20))]; 

[myText setAutoresizingMask:NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin]; 

Produce esto:

enter image description here

2

Es una rotonda poco, pero he encontrado la consulta de la NSTextFieldCell da mucho más preciso/altura resultados fiables que el uso de [NSAttributedString boundingRectWithSize:options:].

Suponiendo la cadena de interés ya está en un NSTextField con el formato apropiado/opciones establecidas envolver, a continuación, consulta la celda de texto de qué tamaño se piensa que tiene que encajar en un ancho especificado:

NSTextField* textField = ...

NSSize cellSize = [textField.cell cellSizeForBounds:NSMakeRect(0, 0, pathText.frame.size.width, CGFLOAT_MAX)];

cellSize.height da la altura que el texto realmente usa cuando se dibuja.

0

encontré que NSString # boundingRectWithSize no es exactamente correcto, lo único que parece que funciona bien es el que se describe aquí: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html

class func sizeForString(_ text : String, withFont font: NSFont, inWidth maxWidth: CGFloat) -> NSSize { 
    let textStorage = NSTextStorage(string: text) 
    let textContainer = NSTextContainer(containerSize: NSSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude)) 
    let layoutManager = NSLayoutManager() 
    layoutManager.addTextContainer(textContainer) 
    textStorage.addLayoutManager(layoutManager) 
    textStorage.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, textStorage.length)) 
textContainer.lineFragmentPadding = 0 
    layoutManager.glyphRange(for: textContainer) 
    return layoutManager.usedRect(for: textContainer).size 
} 
Cuestiones relacionadas