Próbuję uzyskać prostokąt dla przypisanego ciągu, ale wywołanie boundingRectWithSize nie uwzględnia rozmiaru, który przekazuję i zwraca prostokąt o wysokości pojedynczej linii w przeciwieństwie do dużej wysokości (jest to długi ciąg). Eksperymentowałem, przekazując bardzo dużą wartość wysokości, a także 0, jak w poniższym kodzie, ale zwracany prostokąt jest zawsze taki sam.
CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
options:NSStringDrawingUsesDeviceMetrics
context:nil];
Czy to jest zepsute, czy muszę zrobić coś innego, aby zwróciło prostokąt dla zawiniętego tekstu?
objective-c
nsattributedstring
RunLoop
źródło
źródło
lineBreakMode
?Odpowiedzi:
Wygląda na to, że nie podałeś właściwych opcji. Do pakowania etykiet należy zapewnić co najmniej:
Uwaga: jeśli oryginalna szerokość tekstu jest mniejsza niż 300. f nie będzie zawijania linii, więc upewnij się, że rozmiar zszywania jest prawidłowy, w przeciwnym razie nadal uzyskasz błędne wyniki.
źródło
ceilf(paragraphRect.size.height)
, aby został zaokrąglony w górę. Cały czas o tym zapominam i zastanawiam się, dlaczego moje etykiety wciąż się przycinają.boundingRectWithSize:
zawijam swoje obliczenia w CGRectIntegral (), coCGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers
w tym przypadku zaokrągla wysokość i szerokość, aby zapewnić, że nie nastąpi przycinanie, jeśli wysokość lub szerokość są wartością ułamkową.Z jakiegoś powodu boundingRectWithSize zawsze zwraca nieprawidłowy rozmiar. Znalazłem rozwiązanie. Istnieje metoda UItextView -sizeThatFits, która zwraca właściwy rozmiar dla zestawu tekstowego. Dlatego zamiast używać boundingRectWithSize, utwórz UITextView z losową ramką i wywołaj jego sizeThatFits z odpowiednią szerokością i wysokością CGFLOAT_MAX. Zwraca rozmiar, który będzie miał odpowiednią wysokość.
Jeśli obliczasz rozmiar w pętli while, nie zapomnij dodać, że w puli autorelease, ponieważ zostanie utworzonych n liczba utworzonych UITextView, pamięć uruchomieniowa aplikacji wzrośnie, jeśli nie użyjemy puli autoreleasepool.
źródło
UITextView
razy, ileheightForRowAtIndexPath
wywołań metody jest przesadą ? to wymaga czasuEd McManus z pewnością dostarczył klucza do tego, aby to zadziałało. Znalazłem przypadek, który nie działa
rect nie będzie miał prawidłowej wysokości. Zauważ, że inny ciąg (który jest dołączany do ciągu ) został zainicjowany bez słownika atrybutów. Jest to uzasadniony inicjator dla anotherString, ale boundingRectWithSize : w tym przypadku nie podaje dokładnego rozmiaru.
źródło
NSMutableAttributedString
bez atrybutów i otrzymałem zły rozmiar.Moja ostateczna decyzja po długim badaniu:
- boundingRectWithSize
funkcja zwraca prawidłowy rozmiar tylko dla nieprzerwanej sekwencji znaków! W przypadku, gdy łańcuch zawiera spacje lub coś innego (nazywane przez Apple „Niektóre z glifów”) - nie jest możliwe uzyskanie rzeczywistego rozmiaru prostego potrzebnego do wyświetlenia tekstu!Zastąpiłem spacje w moich napisach literami i od razu uzyskałem poprawny wynik.
Apple mówi tutaj: https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize
Ta metoda zwraca rzeczywiste granice glifów w ciągu. Niektóre glify (na przykład spacje) mogą nakładać się na ograniczenia układu określone przez przekazany rozmiar, więc w niektórych przypadkach wartość szerokości składnika rozmiaru elementu zwracana wartość
CGRect
może przekroczyć wartość szerokości parametru rozmiaru. "Konieczne jest więc znalezienie innego sposobu obliczenia rzeczywistego współczynnika ...
Po długim badaniu procesu ostatecznie znaleziono rozwiązanie !!! Nie jestem pewien, czy będzie dobrze działać we wszystkich przypadkach z tym związanych
UITextView
, ale wykryto główną i ważną rzecz!boundingRectWithSize
function, jak równieżCTFramesetterSuggestFrameSizeWithConstraints
(i wiele innych metod) obliczy rozmiar i część tekstu poprawnie, jeśli zostanie użyty poprawny prostokąt. Na przykład -UITextView
matextView.bounds.size.width
- i ta wartość nie jest rzeczywistym prostokątem używanym przez system podczas rysowania tekstuUITextView
.Znalazłem bardzo interesujący parametr i wykonałem proste obliczenia w kodzie:
A magia działa - teraz wszystkie moje teksty są poprawne! Cieszyć się!
źródło
Wersja Swift four
Pomiar tekstu za pomocą CTFramesetter działa najlepiej, ponieważ zapewnia rozmiary całkowite i dobrze obsługuje znaki emoji i inne znaki Unicode.
źródło
Nie udało mi się z żadną z tych sugestii. Mój ciąg zawierał wypunktowane znaki Unicode i podejrzewam, że powodowały żal w obliczeniach. Zauważyłem, że UITextView radził sobie dobrze z rysunkiem, więc spojrzałem na to, aby wykorzystać jego obliczenia. Zrobiłem co następuje, co prawdopodobnie nie jest tak optymalne jak metody rysowania NSString, ale przynajmniej jest dokładne. Jest to również nieco bardziej optymalne niż inicjowanie UITextView tylko do wywołania
-sizeThatFits:
.źródło
Jeśli chcesz uzyskać prostokąt ograniczający, obcięcie ogona, to pytanie może ci pomóc.
źródło
Okazuje się, że KAŻDA część NSAttributedString musi mieć ustawiony słownik z co najmniej ustawieniami NSFontAttributeName i NSForegroundColorAttributeName, jeśli chcesz, aby boundingRectWithSize faktycznie działało!
Nigdzie nie widzę tego udokumentowanego.
źródło
@warrenm Przykro mi to mówić, że metoda framesetter nie zadziałała.
Mam to Ta funkcja może pomóc nam określić rozmiar ramki potrzebny dla zakresu ciągów NSAttributedString w zestawie SDK telefonu iPhone / iPada dla danej szerokości:
Może służyć do dynamicznej wysokości komórek UITableView
Podziękowania dla HADDAD ISSA >>> http://haddadissa.blogspot.in/2010/09/compute-needed-heigh-for-fixed-width-of.html
źródło
#import <CoreText/CoreText.h>
Zauważyłem, że preferowane rozwiązanie nie obsługuje łamania linii.
Odkryłem, że to podejście działa we wszystkich przypadkach:
źródło
Miałem ten sam problem z brakiem dokładnego rozmiaru przy użyciu tych technik i zmieniłem swoje podejście, aby to działało.
Mam długi przypisany ciąg, który próbowałem dopasować do widoku przewijania, aby wyświetlał się poprawnie bez obcięcia. Aby tekst działał niezawodnie, w ogóle nie ustawiłem wysokości jako ograniczenia, a zamiast tego pozwoliłem, aby wewnętrzny rozmiar przejął. Teraz tekst wyświetla się poprawnie bez obcięcia i nie muszę obliczać wysokości.
Przypuszczam, że gdybym musiał niezawodnie uzyskać wysokość, utworzyłbym widok, który jest ukryty i te ograniczenia, i uzyskałbym wysokość ramy po zastosowaniu ograniczeń.
źródło
Jestem trochę spóźniony do gry - ale próbowałem znaleźć sposób, który działa, aby znaleźć obwiednię, która będzie pasować do przypisanego ciągu, aby utworzyć pierścień ostrości, tak jak robi to edycja pliku w Finderze. wszystko, czego próbowałem, zawiodło, gdy na końcu ciągu znajdują się spacje lub wiele spacji w ciągu.
boundingRectWithSize
nie udaje się również z tego powoduCTFramesetterCreateWithAttributedString
.Użycie
NSLayoutManager
poniższego kodu wydaje się załatwiać sprawę we wszystkich przypadkach, które znalazłem do tej pory i zwraca prostokąt, który idealnie ogranicza ciąg. Bonus: jeśli zaznaczysz tekst, krawędzie zaznaczenia idą w górę do granic zwróconego prostego. Poniższy kod używa layoutManager z plikuNSTextView
.źródło
Działa doskonale na wszystkich czcionkach!
źródło
Miałem ten sam problem, ale zauważyłem, że ograniczenie wysokości zostało ustawione poprawnie. Więc zrobiłem co następuje:
źródło
Wypróbowałem wszystko na tej stronie i nadal miałem jeden przypadek dla UILabel, który nie był poprawnie formatowany. Faktyczne ustawienie atrybutu attributeText na etykiecie ostatecznie rozwiązało problem.
źródło
Zauważyłem tylko, że prostokąt, z którego powrócił,
(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context
miałby większą szerokość niż ta, którą przekazałem. Kiedy to się stanie, mój ciąg zostałby obcięty. Rozwiązałem to w ten sposób:Aby uzyskać więcej kontekstu; Miałem tekst wieloliniowy i próbowałem znaleźć odpowiednią wysokość, aby go wyświetlić. BoundRectWithSize czasami zwracało szerokość większą niż to, co określiłem, więc kiedy użyłem mojej przeszłej szerokości i obliczonej wysokości do wyświetlenia mojego tekstu, to ucięty. Z testowania, gdy boundingRectWithSize użyło niewłaściwej szerokości, wartość spowodowałaby skrócenie wysokości o 1 wiersz. Sprawdzę więc, czy szerokość jest większa, a jeśli tak, dodajmy linię lineHeight czcionki, aby zapewnić wystarczającą ilość miejsca, aby uniknąć obcięcia.
źródło
jeśli ramka etykiety nie dodaje 10, ta metoda nigdy nie zadziała! mam nadzieję, że to może ci pomóc! powodzenia.
źródło
}
źródło
Chciałbym dodać swoje przemyślenia, ponieważ miałem dokładnie ten sam problem.
Używałem,
UITextView
ponieważ miał ładniejsze wyrównanie tekstu (justowanie, które w tamtym czasie nie było dostępneUILabel
), ale w celu „symulacji” nieinteraktywnego, nieprzewijalnegoUILabel
, całkowicie wyłączyłem przewijanie, odbijanie i interakcję z użytkownikiem .Oczywiście problem polegał na tym, że tekst był dynamiczny i chociaż szerokość byłaby stała, wysokość powinna być przeliczana za każdym razem, gdy ustawiam nową wartość tekstu.
boundingRectWithSize
w ogóle nie działało dobrze, z tego, co widziałem,UITextView
dodawało trochę marginesu na górze, któryboundingRectWithSize
nie mógł się liczyć, stąd pobrana wysokośćboundingRectWithSize
była mniejsza niż powinna.Ponieważ tekst nie miał być aktualizowany szybko, jest używany tylko do niektórych informacji, które mogą być aktualizowane najczęściej co 2-3 sekundy, zdecydowałem się na następujące podejście:
* Powyższy kod nie jest bezpośrednio kopiowany z mojego źródła, musiałem go dostosować / wyczyścić z wielu innych rzeczy, które nie są potrzebne w tym artykule. Nie bierz tego za kod kopiuj-wklej i zadziała.
Oczywistą wadą jest to, że ma on przydzielanie i zwalnianie dla każdego połączenia.
Ale zaletą jest to, że unikasz zależności od zgodności między sposobem, w jaki boundingRectWithSize rysuje tekst i oblicza jego rozmiar, a implementacją rysowania tekstu w
UITextView
(lubUILabel
które również można użyć po prostu zastąpićUITextView
zUILabel
). W ten sposób można uniknąć wszelkich „błędów”, które może mieć Apple.PS Wydawałoby się, że nie powinieneś potrzebować tego "temp"
UITextView
i możesz po prostu zapytaćsizeThatFits
bezpośrednio od celu, jednak to nie zadziałało dla mnie. Chociaż logika powiedziałaby, że powinno działać, a przydzielanie / zwalnianie tymczasowychUITextView
nie jest potrzebne, tak się nie stało. Ale to rozwiązanie działało bezbłędnie dla każdego tekstu, który bym wstawił.źródło
Ok, więc spędziłem dużo czasu na debugowaniu tego. Dowiedziałem się, że maksymalna wysokość tekstu zdefiniowana przez
boundingRectWithSize
pozwala na wyświetlanie tekstu przez mojeUITextView
jest mniejsza niż rozmiar ramki.W moim przypadku ramka ma maksymalnie 140 punktów, ale UITextView toleruje teksty maksymalnie 131 punktów.
Musiałem to rozgryźć ręcznie i zakodować „prawdziwą” maksymalną wysokość.
Oto moje rozwiązanie:
źródło