2012-08-23 6 views
12

Sto tentando di ridimensionare automaticamente un campo/vista di testo in base alla sua larghezza corrente. In altre parole, voglio che la larghezza rimanga costante, ma ridimensiona l'altezza in base al testo che gli viene fornito.NSString boundingRectWithSize che sottostima leggermente l'altezza corretta - perché?

Sembra funzionare, ma per qualche motivo è allineato alla parte inferiore della mia finestra nonostante gli sforzi per spostarlo manualmente indietro. Qualcuno può vedere cosa sto facendo di sbagliato qui?

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: Anche quando si sposta manualmente il telaio è chiaro che il testo è ancora vengano tagliate. La nuova dimensione adattata non è proprio lì. enter image description here

questo è in riferimento a: NSString boundingRectWithSize slightly underestimating the correct width - why? e NSTextView or NSTextField automatically resize bounds/frame?

+0

forse cambiare altezza da 200 a qualcosa di così grande in modo che il telaio le dimensioni sanno crescere verticalmente. – rein

+0

@rein Continuo a giocare con questo e mentre effettivamente ridimensiona il nuovo fotogramma il suo testo di ritaglio ancora sul fondo. Il nuovo telaio non è abbastanza grande. Vedi la domanda aggiornata per un nuovo screenshot. –

risposta

15

Ho avuto lo stesso problema. Ho trovato quanto segue in the Documentation:

Per disegnare correttamente e dimensione del testo su più righe, passano NSStringDrawingUsesLineFragmentOrigin nel parametro opzioni.

Questo metodo restituisce dimensioni frazionarie (nel componente di dimensioni di restituito CGRect); per utilizzare una dimensione restituita in vista dimensioni, è necessario aumentare il valore al numero intero più vicino più vicino utilizzando la funzione ceil.

Quindi questo risolto per me:

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)

Uno Swift 3 modo alternativo per fare questo sarebbe:

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

See this answer per un esempio Objective-C.

+0

Grazie per questo, mi ha aiutato molto – phyzalis

+2

OR'ing con NSLineBreakByWordWrapping non è valido e non funziona comunque per me. Non è un membro dell'enumerazione NSStringDrawingOptions. – iphone007

+0

Hmm .. Hai ragione! Hai provato con 'NSStringDrawingUsesLineFragmentOrigin'? Ha funzionato? Modificherei quindi il frammento. –

1

Questo è quello che ho finito per andare con (almeno per il momento) sembra funzionare bene, però mi sento ancora come se ci è un modo migliore per farlo.

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 questo:

enter image description here

2

è un po 'rotonda, ma ho trovato l'interrogazione del NSTextFieldCell dà molto più preciso/risultati altezza affidabili rispetto all'utilizzo [NSAttributedString boundingRectWithSize:options:].

Assumendo la stringa di interesse è già in una NSTextField con la formattazione appropriata/opzioni impostate confezionamento, poi interrogare la cella di testo per i quali dimensioni si pensa che ha bisogno di stare in una larghezza specificata:

NSTextField* textField = ...

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

cellSize.height fornisce l'altezza che il testo effettivamente utilizza quando viene disegnato.

0

ho scoperto che NSString # boundingRectWithSize non è mai esattamente corretto, l'unica cosa che sembra funzionare bene è quello descritto qui: 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 
} 
Problemi correlati