Mam UITableView
działający pod iOS 8 i używam automatycznych wysokości komórek od ograniczeń w serii ujęć.
Jedna z moich komórek zawiera jedną UITextView
i muszę ją skurczyć i rozwinąć na podstawie danych wprowadzonych przez użytkownika - dotknij, aby zmniejszyć / rozwinąć tekst.
Robię to, dodając ograniczenie czasu wykonywania do widoku tekstu i zmieniając stałą ograniczenia w odpowiedzi na zdarzenia użytkownika:
-(void)collapse:(BOOL)collapse; {
_collapsed = collapse;
if(collapse)
[_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
else
[_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];
[self setNeedsUpdateConstraints];
}
Ilekroć to robię, pakuję go w tableView
aktualizacje i dzwonię [tableView setNeedsUpdateConstraints]
:
[tableView beginUpdates];
[_briefCell collapse:!_showFullBriefText];
[tableView setNeedsUpdateConstraints];
// I have also tried
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.
[tableView endUpdates];
Kiedy to robię, moja komórka rozszerza się (i animuje podczas tej operacji), ale pojawia się ostrzeżenie o ograniczeniach:
2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",
"<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-| (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'] (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>
388 to moja obliczona wysokość, pozostałe ograniczenia UITextView
są moje od Xcode / IB.
Ostatnia przeszkadza mi - zgaduję, że UIView-Encapsulated-Layout-Height
jest to obliczona wysokość komórki, gdy jest ona renderowana po raz pierwszy - (ustawiłem moją UITextView
wysokość na> = 70,0), jednak nie wydaje się słuszne, aby to pochodne ograniczenie nadpisało zaktualizowano cnstraint użytkownika.
Co gorsza, chociaż kod układu mówi, że próbuje przełamać moje ograniczenie wysokości, nie robi tego - kontynuuje ponowne obliczanie wysokości komórki i wszystko rysuje tak, jak bym chciał.
Czym więc jest NSLayoutConstraint
UIView-Encapsulated-Layout-Height
(domyślam się, że jest to obliczona wysokość dla automatycznego określania rozmiaru komórki) i jak powinienem zmusić ją do ponownego przeliczenia?
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
. Myślę, że początkowo ustawienie maski automatycznego zatrzymywania powstrzymuje dodawanie ostatniego ograniczenia. Znalazłem to rozwiązanie tutaj: github.com/wordpress-mobile/WordPress-iOS/commit/…<rect key="frame" x="0.0" y="0.0" width="600" height="110"/>
w definicji, co prowadzi mnie do przekonania, że to błąd IB . Przynajmniej moja była zresztą.Odpowiedzi:
Spróbuj obniżyć swój priorytet
_collapsedtextHeightConstraint
do 999. W ten sposóbUIView-Encapsulated-Layout-Height
ograniczenie dostarczone przez system zawsze ma pierwszeństwo.Opiera się na tym, co wrócisz
-tableView:heightForRowAtIndexPath:
. Pamiętaj o zwróceniu właściwej wartości i własnego ograniczenia, a wygenerowane powinno być takie samo. Niższy priorytet dla własnego ograniczenia jest potrzebny tylko tymczasowo, aby zapobiec konfliktom podczas animacji zwinięcia / rozwinięcia w locie.źródło
UIView-Encapsulated-Layout-Height
Ograniczeniem jest dodawana przez UITableView Gdy szczyty są ustalone. Wysokość obliczam na podstawiesystemLayoutSizeFittingSize
contentView. TutajUIView-Encapsulated-Layout-Height
nie ma znaczenia. Następnie tableView ustawia contentSize jawnie na wartość zwracaną przezheightForRowAtIndexPath:
. W takim przypadku poprawne jest obniżenie priorytetu naszych ograniczeń niestandardowych, ponieważ ograniczenie tableView musi mieć pierwszeństwo po obliczeniu RowHeights.UIView-Encapsulated-Layout-Height
nie mam racji, jeśli nie obniżę priorytetu ...UIView-Encapsulated-Layout-Width
w moim przypadku jest po prostu błędne, ale wydaje się, że jest ono preferowane w stosunku do moich wyraźnych ograniczeń w czasie wykonywania.Mam podobny scenariusz: widok tabeli z jedną komórką wiersza, w którym znajduje się kilka wierszy obiektów UILabel. Używam iOS 8 i autolayout.
Kiedy się obróciłem, otrzymałem niewłaściwy system obliczoną wysokość wiersza (43,5 to znacznie mniej niż rzeczywista wysokość). To wygląda jak:
To nie tylko ostrzeżenie. Układ mojej komórki widoku tabeli jest okropny - cały tekst nakłada się na jedną linię tekstu.
Zaskakuje mnie, że następujący wiersz „naprawia” mój problem magicznie (autoukład nic nie narzeka i otrzymuję to, czego oczekuję na ekranie):
z tą linią lub bez:
źródło
estimatedRowHeight
częściejcellForRowAtIndexPath
nazywa się początkowo. wysokość widoku tabeli podzielona przez szacunkowe czasy RowHeight, a dokładnie. Na 12-calowym iPadzie Pro może to być liczba w tysiącach, co utrudni źródło danych i może spowodować znaczne opóźnienie.Byłem w stanie uzyskać ostrzeżenie, aby zniknęło, określając priorytet jednej z wartości w ograniczeniu, które komunikaty ostrzegawcze mówiły, że musiało się złamać (poniżej
"Will attempt to recover by breaking constraint"
). Wygląda na to, że o ile ustawię priorytet na coś większego niż49
, ostrzeżenie zniknie.Dla mnie oznaczało to zmianę mojego ograniczenia, ostrzeżenie mówiło, że próbuje się złamać:
@"V:|[contentLabel]-[quoteeLabel]|"
do:
@"V:|-0@500-[contentLabel]-[quoteeLabel]|"
W rzeczywistości mogę dodać priorytet do dowolnego elementu tego ograniczenia i zadziała. Nie ma znaczenia, który z nich. Moje komórki osiągają odpowiednią wysokość, a ostrzeżenie nie jest wyświetlane. Na przykład Roger, spróbuj dodać
@500
zaraz po388
ograniczeniu wartości wysokości (np388@500
.).Nie jestem do końca pewien, dlaczego to działa, ale przeprowadziłem trochę dochodzenia. W wyliczeniu NSLayoutPriority wydaje się, że
NSLayoutPriorityFittingSizeCompression
poziom priorytetu to50
. Dokumentacja dla tego poziomu priorytetu mówi:Dokumentacja dla wskazanej
fittingSize
wiadomości brzmi:Nie wykopałem poza tym, ale wydaje się mieć sens, że ma to coś wspólnego z tym, gdzie leży problem.
źródło
99,9% czasu, przy użyciu niestandardowych komórek lub nagłówków, wszystkie konflikty
UITableViews
występują, gdy tabela ładuje się po raz pierwszy. Po załadowaniu zwykle nie zobaczysz ponownie konfliktu.Dzieje się tak, ponieważ większość programistów zazwyczaj używa stałej wysokości lub pewnego rodzaju ograniczenia kotwiczenia do układania elementu w komórce / nagłówku. Konflikt występuje, ponieważ przy
UITableView
pierwszym ładowaniu / rozkładaniu wysokość jego komórek jest ustawiana na 0. To oczywiście koliduje z własnymi ograniczeniami. Aby rozwiązać ten problem, po prostu ustaw dowolne ograniczenia stałej wysokości na niższy priorytet (.defaultHigh
). Przeczytaj uważnie komunikat konsoli i sprawdź, jakie ograniczenie system układu postanowił złamać. Zwykle należy zmienić priorytet. Możesz zmienić priorytet w ten sposób:źródło
Udało mi się rozwiązać ten problem poprzez usunięcie nieprawdziwy
cell.layoutIfNeeded()
, że miałem w moimtableView
„scellForRowAt
metody.źródło
Zamiast informować widok tabeli, aby zaktualizował ograniczenia, spróbuj ponownie załadować komórkę:
UIView-Encapsulated-Layout-Height
jest prawdopodobnie wysokością widoku tabeli obliczoną dla komórki podczas ładowania początkowego, na podstawie ograniczeń komórki w tym czasie.źródło
Inna możliwość:
Jeśli używasz automatycznego układu do obliczania wysokości komórki (wysokość contentView, przez większość czasu jak poniżej), a jeśli masz separator uitableview, musisz dodać wysokość separatora, aby zwrócić wysokość komórki. Gdy uzyskasz prawidłową wysokość, nie pojawi się ostrzeżenie o autoukładzie.
źródło
UITableViewAutomaticDimension
naheightForRowAtIndexPath
wrócę[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] + 0.1
[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 0.1
Jak wspomniał w komentarzu Jesse , działa to dla mnie:
Do Twojej wiadomości, ten problem nie występuje w iOS 10.
źródło
Wystąpił ten błąd podczas używania UITableViewAutomaticDimension i zmiany ograniczenia wysokości w widoku wewnątrz komórki.
W końcu doszedłem do wniosku, że było to spowodowane tym, że stała wartość ograniczenia nie była zaokrąglana w górę do najbliższej liczby całkowitej.
źródło
Dostosowanie widoku tekstu do jego zawartości i zaktualizowanie stałej ograniczenia wysokości do wynikowej wysokości, naprawiło
UIView-Encapsulated-Layout-Height
konflikt ograniczeń dla mnie, np .:źródło
Po spędzeniu kilku godzin na drapaniu się w głowę tym błędem w końcu znalazłem rozwiązanie, które zadziałało dla mnie. moim głównym problemem było to, że zarejestrowałem wiele końcówek dla różnych typów komórek, ale konkretnie jeden typ komórki mógł mieć różne rozmiary (nie wszystkie wystąpienia tej komórki będą tego samego rozmiaru). więc problem pojawił się, gdy widok tabeli próbował usunąć kolejkę z komórki tego typu i okazało się, że ma inną wysokość. Rozwiązałem to przez ustawienie
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});
za każdym razem, gdy komórka ma dane do obliczenia swojego rozmiaru. Myślę, że może być
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
coś jak
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; cell.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});
Mam nadzieję że to pomoże!
źródło
TableView uzyskać wysokość dla komórki w indexPath od delegata. następnie pobierz komórkę z
cellForRowAtIndexPath
:jeśli cell.contentView.height: 0 // <-> (UIView-Encapsulated-Layout-Height: 0 @ 1000) góra (10 @ 1000) jest w konflikcie z (UIView-Encapsulated-Layout-Height: 0 @ 1000),
ponieważ ich priorytety są równe 1000. Potrzebujemy ustawić najwyższy priorytet w ramach
UIView-Encapsulated-Layout-Height
priorytetu.źródło
Otrzymałem taki komunikat:
Używam niestandardowego
UITableViewCell
zUITableViewAutomaticDimension
wysokością. I zaimplementowałem tęestimatedHeightForRowAtIndex:
metodę.Ograniczenie, które dawało mi problemy, wyglądało mniej więcej tak
Zmiana ograniczenia na to rozwiąże problem, ale podobnie jak inna odpowiedź, poczułem, że to nie jest poprawne, ponieważ obniża priorytet ograniczenia, które chcę być wymagane:
Zauważyłem jednak, że jeśli po prostu usunę priorytet, to również działa i nie otrzymuję dzienników ograniczeń zerwania:
To trochę tajemnica, jaka jest różnica między
|-6-[title]-6-|
i|-[title-|
. Ale określenie rozmiaru nie jest dla mnie problemem i pozbywa się dzienników i nie muszę obniżać priorytetu moich wymaganych ograniczeń.źródło
Ustaw to
view.translatesAutoresizingMaskIntoConstraints = NO;
powinno rozwiązać ten problem.źródło
Miałem podobny problem z komórką widoku kolekcji.
Rozwiązałem go, obniżając priorytet ostatecznego ograniczenia, które było połączone z dolną częścią komórki (ostatnia w łańcuchu od góry do dołu widoku - to ostatecznie decyduje o jego wysokości) do 999.
Wysokość celi była prawidłowa, a ostrzeżenia zniknęły.
źródło