iOS: multi-line UILabel in Auto Layout

Mam problem z uzyskaniem bardzo podstawowego zachowania układu za pomocą Auto Layout. Mój kontroler widoku wygląda tak w IB:

Tutaj wpisz opis obrazka

The top label is the title label, I don ' t know how many linijki it will be. Potrzebuję etykiety tytułowej, aby wyświetlić wszystkie wiersze tekstu. Potrzebuję również pozostałych dwóch etykiet i małego obrazu, który powinien być umieszczony tuż pod tytułem, niezależnie od tego, jak wysoki jest. Ustawiłem ograniczenia odstępów pionowych między etykietami i małym obrazkiem jako ograniczenie górnego odstępu między etykietą tytułową a jej superview oraz ograniczenie dolnego odstępu między małym obrazkiem a superview. Biały UIView nie ma ograniczenia wysokości, więc powinien rozciągać się pionowo, aby zawierać jego podwidywacze. Ustawiłem liczbę linii dla etykiety tytułowej na 0.

Jak zmienić rozmiar etykiety tytułowej, aby pasowała do liczby linii wymaganych przez ciąg znaków? Rozumiem, że nie mogę używać metod setFrame, ponieważ używam układu Auto. I Ja muszę użyć układu Auto, ponieważ potrzebuję tych innych widoków, aby pozostać poniżej etykiety tytułu (stąd ograniczenia).

Jak mogę to zrobić?

Author: James Harpe, 2012-10-09

8 answers

Użyj {[1] } na UILabel, a autolayout powinien zająć się resztą.

[label setPreferredMaxLayoutWidth:200.0];

Zobacz dokumentację UILabel .

Aktualizacja:

Wystarczy ustawić ograniczenie wysokości w storyboard na większe lub równe", nie ma potrzeby setPreferredMaxLayoutWidth.

 244
Author: mwhuss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-30 08:32:32

Rozszerz liczbę linii Zestawu etykiet do 0, a także, co ważniejsze, dla automatycznego ustawiania wysokości układu do > = x. UKŁAD automatyczny zrobi resztę. Możesz również zawierać inne elementy oparte na poprzednim elemencie, aby prawidłowo je ustawić.

auto layout

 209
Author: Charlie Wu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-26 11:06:58

Źródło: http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

Wewnętrzna wielkość zawartości tekstu wielowierszowego

Wewnętrzny rozmiar zawartości UILabel i NSTextField jest niejednoznaczny dla tekstu wielowierszowego. Wysokość tekstu zależy od szerokości linii, która nie jest jeszcze określona przy rozwiązywaniu ograniczeń. Aby rozwiązać ten problem, obie klasy mają nową właściwość o nazwie preferredMaxLayoutWidth, która określa maksymalną linię szerokość do obliczania wielkości wewnętrznej zawartości.

Ponieważ zwykle nie znamy tej wartości z góry, musimy przyjąć podejście dwuetapowe, aby to osiągnąć. Najpierw pozwalamy układowi automatycznemu wykonywać swoją pracę, a następnie używamy wynikowej ramki w przebiegu układu, aby zaktualizować preferowaną maksymalną szerokość i ponownie wyzwalać układ.

- (void)layoutSubviews
{
    [super layoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [super layoutSubviews];
}

Pierwsze wywołanie [super layoutSubviews] jest konieczne, aby etykieta miała ustawioną ramkę, podczas gdy drugie wywołanie jest konieczne, aby zaktualizować układ po zmiana. Jeśli pominiemy drugie wywołanie, otrzymamy błąd NSInternalInconsistencyException, ponieważ wprowadziliśmy zmiany w przebiegu układu, które wymagają aktualizacji ograniczeń, ale nie uruchomiliśmy ponownie układu.

Możemy to zrobić również w samej podklasie etykiet:

@implementation MyLabel
- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

W tym przypadku nie musimy najpierw wywoływać [super layoutSubviews], ponieważ po wywołaniu layoutSubviews mamy już ramkę na samej etykiecie.

Aby dokonać tej regulacji z kontrolera widoku poziom, podłączamy się do viewDidLayoutSubviews. W tym momencie ramki pierwszego przejścia układu Auto są już ustawione i możemy ich użyć do ustawienia preferowanej maksymalnej szerokości.

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [self.view layoutIfNeeded];
}

na koniec upewnij się, że na etykiecie nie ma wyraźnego ograniczenia wysokości, które ma wyższy priorytet niż priorytet odporności na kompresję zawartości etykiety. W przeciwnym razie przebije obliczoną wysokość zawartości. Sprawdź wszystkie ograniczenia, które mogą mieć wpływ na etykiety wzrost.

 44
Author: Anton Matosov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-21 07:30:13

Walczyłem właśnie z tym scenariuszem, ale z jeszcze kilkoma widokami, które wymagały zmiany rozmiaru i przesunięcia w dół w razie potrzeby. Doprowadzało mnie to do szału, ale w końcu to rozgryzłem.

Oto klucz: Interface Builder lubi dodawać dodatkowe ograniczenia podczas dodawania i przenoszenia widoków i możesz tego nie zauważyć. W moim przypadku miałem widok w połowie drogi w dół, który miał dodatkowe ograniczenie, które określało Rozmiar między nim a jego superview, w zasadzie przypinając go do tego punktu. To oznaczało, że nic powyżej nie może zmienić rozmiaru, ponieważ byłoby to sprzeczne z tym ograniczeniem.

Łatwo stwierdzić, czy tak jest, próbując ręcznie zmienić rozmiar etykiety. Czy IB pozwala ci go hodować? Jeśli tak, czy poniższe etykiety poruszają się zgodnie z oczekiwaniami? Przed zmianą rozmiaru upewnij się, że oba te elementy zostały sprawdzone, aby zobaczyć, jak ograniczenia będą przesuwać widoki:

IB Menu

Jeśli widok jest zablokowany, postępuj zgodnie z widokami znajdującymi się pod nim i upewnij się, że jeden z nich nie ma górnej spacji do superwizji. Następnie upewnij się, że opcja liczba linii dla etykiety jest ustawiona na 0 i powinna zająć się resztą.

 16
Author: Cory Imdieke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-18 21:03:07

I find you need the following:

  • a top constraint
  • ograniczenie wiodące (np. Lewa Strona)
  • ograniczenie końcowe (np. prawa strona)
  • Ustaw priorytet Przytulania zawartości, poziomy na niski, tak aby wypełniał daną przestrzeń, jeśli tekst jest krótki.
  • Ustaw odporność na kompresję zawartości, poziomą do niskiej, aby owinąć zamiast próbować stać się szerszym.
  • Ustaw liczbę linii na 0.
  • Ustaw tryb łamania linii na zawijanie słów.
 4
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 01:01:03

Żadne z różnych rozwiązań znalezionych w wielu tematach na ten temat nie działało idealnie dla mojego przypadku (X dynamiczne etykiety wieloliniowe w dynamicznych komórkach widoku tabeli) .

Znalazłem na to sposób:

Po ustawieniu ograniczeń na etykiecie i ustaw jej właściwość multiline na 0, Utwórz podklasę UILabel ; nazwałem ją AutoLayoutLabel:

@implementation AutoLayoutLabel

- (void)layoutSubviews{
    [self setNeedsUpdateConstraints];
    [super layoutSubviews];
    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
}

@end
 0
Author: Tanguy G.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-02 16:34:10

Mam UITableViewCell, który ma etykietę zawijania tekstu. Pracowałem pakowania tekstu w następujący sposób.

1) Ustaw ograniczenia UILabel w następujący sposób.

Tutaj wpisz opis obrazka

2) Zestaw Nr. linii do 0.

3) dodano ograniczenie wysokości UILabel do UITableViewCell.

@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!

4) Na UITableViewCell:

priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5
 0
Author: A.G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 06:33:07

Można to zrobić w jeden sposób... Wraz ze wzrostem długości tekstu spróbuj zmienić (zmniejszyć) wielkość czcionki na etykiecie za pomocą

Label.adjustsFontSizeToFitWidth = YES;
 -8
Author: user1662392,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 13:21:58