2011-02-17 10 views
6

Czy istnieje odpowiednia metoda w AppKit (dla Cocoa na Mac OS X), która robi to samo, co UIKit's [NSString sizeWithFont:constrainedToSize:]?UIKit [NSString sizeWithFont: constrainedToSize:] w AppKit

Jeśli nie, w jaki sposób mogę uzyskać ilość miejsca potrzebną do renderowania określonego ciągu ograniczonego do szerokości/wysokości?

Aktualizacja: Poniżej znajduje się fragment kodu, którego używam, a którego oczekuję, że przyniesie oczekiwane wyniki.

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSFont systemFontOfSize: [NSFont smallSystemFontSize]], NSFontAttributeName, 
          [NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName, 
          nil]; 
NSSize size = NSMakeSize(200.0, MAXFLOAT); 
NSRect bounds; 

bounds = [@"This is a really really really really really really really long string that won't fit on one line" 
      boundingRectWithSize: size 
      options: NSStringDrawingUsesFontLeading 
      attributes: attributes]; 

NSLog(@"height: %02f, width: %02f", bounds.size.height, bounds.size.width); 

Spodziewam się, że szerokość wyjścia będzie 200, a wysokość byłaby czymś większym niż wysokość pojedynczej linii, jednak produkuje:

height: 14.000000, width: 466.619141 

Dzięki!

+1

duplikat: http://stackoverflow.com/questions/ 2349692/whats-the-equivalent-sizewithfont-method-for-the-mac. Nikt nie szuka w tych dniach? –

+3

Szukałem, ale, zdumiewająco, nie znalazłem tego. Bez względu na sizeWithAttributes: nie, afaik, wsparcie ograniczające szerokość. –

+4

Nie jest to duplikat z powodu elementu constraint, którego brakuje w tym drugim pytaniu. –

Odpowiedz

1

EDYCJA: Powinieneś być w stanie robić rzeczy normalnie w Lion i później. Opisane poniżej problemy zostały naprawione.


Nie ma możliwości dokładnego zmierzenia tekstu wśród bieżących interfejsów API systemu Mac OS X.

Istnieje kilka interfejsów API, które obiecują działać, ale nie. To jedna z nich; Core Text's function for this purpose to kolejny. Niektóre metody zwracają wyniki bliskie, ale błędne; niektóre wyniki zwrotu, które wydają się nic nie znaczyć. Nie zgłosiłem jeszcze żadnych błędów, ale kiedy to zrobię, zmienię liczby radarów w tę odpowiedź. Powinieneś również zgłosić błąd i dołączyć swój kod do małego przykładowego projektu.

[Wygląda na to, że już napisałem tekst podstawowy: 8666756. Jest zamknięty jako duplikat bliżej nieokreślonego innego błędu. Kakao, I złożony 9022238 o sposobie Dave zasugerował, a jutro złoży dwa błędy NSLayoutManager.]

This is the closest solution I've found.

+0

Twój link jest uszkodzony. – livingtech

+0

@livingtech: Zaktualizowałem swoją odpowiedź. Dzięki. –

+0

@PeterHosey Mówisz, że działa na Lionie, ale nie wydaje mi się to ... Oto moje pytanie. Http://stackoverflow.com/questions/11766189/how-do-we-measure-visible-bounds-of -text-in-cocoa i powiązane pytanie jest na http://stackoverflow.com/questions/11877791/what-does-the-nsstringdrawingusesdevicemetrics-flag-mean-and-how-do-we-use-it/ – trss

-4

Jeśli przeszukujesz dokumentację pod kątem NSString, znajdziesz "Wzorzec dodawania zestawów aplikacji NSString", który jest w zasadzie analogiczny do odpowiednika UIKit.

-[NSString sizeWithAttributes:] 

to metoda, której szukasz.

+1

Czy istnieje atrybut określający sizeWithAttributes: aby ograniczyć jego szerokość/wysokość? –

1

Jeśli chcesz ograniczyć ciąg do określonego rozmiaru, używaj -[NSString boundingRectWithSize:options:attributes:]. Numer .size zwróconego NSRect to rozmiar, którego szukasz.

+0

Dodałem kod, który spodziewałbym się zastosować w pytaniu, ale wyraźnie nie. Czy mógłbyś wskazać mi właściwy kierunek? Dzięki! –

+0

Zgoda ... to na pewno nie działa, nie wiem dlaczego. – livingtech

+0

Jak wspominała Aki, musisz podać opcję 'NSStringDrawingUsesLineFragmentOrigin' dla obliczeń wieloliniowych. – livingtech

6

Nowsza kategoria API NSExtendedStringDrawing (metody z argumentem NSStringDrawingOptions) zachowuje się w trybie pojedynczego wiersza. Jeśli chcesz zmierzyć/renderować w trybie wielowierszowym, chcesz określić NSStringDrawingUsesLineFragmentOrigin.

+3

OMG! TAK! Ten nieszkodliwy komentarz sprawił, że 'boundingRectWithSize: options: attributes:' magically work for me! 'NSStringDrawingUsesLineFragmentOrigin' jest ważną opcją. – livingtech

13

Spróbuj tego:

bounds = [value boundingRectWithSize:size options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; 
+5

Dlaczego nie jest to zaakceptowana odpowiedź? –

+0

'NSLineBreakByWordWrapping' nie jest opcją' NSStringDrawingOptions'. Jest zdefiniowany jako 0, więc nie ma żadnego efektu. – titaniumdecoy

+0

@titaniumdecoy 0 nie oznacza braku efektu, oznacza to domyślnie. – coneybeare

1

Oto bardziej kompletny przykład tego, jak można to zrobić przy użyciu boundingRectWithSize.

// get the text field 
NSTextField* field = (NSTextField*)view; 

// create the new font for the text field 
NSFont* newFont = [NSFont fontWithName:@"Trebuchet MS" size:11.0]; 

// set the font on the text field 
[field setFont:newFont]; 

// calculate the size the textfield needs to be in order to display the text properly 
NSString* text  = field.stringValue; 
NSInteger maxWidth = field.frame.size.width; 
NSInteger maxHeight = 20000; 
CGSize constraint = CGSizeMake(maxWidth, maxHeight); 
NSDictionary* attrs = [NSDictionary dictionaryWithObjectsAndKeys:NSFontAttributeName,newFont, nil]; 
NSRect newBounds = [text boundingRectWithSize:constraint 
             options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin 
             attributes:attrs]; 

// set the size of the text field to the calculated size 
field.frame = NSMakeRect(field.frame.origin.x, field.frame.origin.y, field.frame.size.width, newBounds.size.height); 

Oczywiście, dla dodatkowej informacji, zapoznać się z dokumentacją Apple: