resize superview po dynamicznej zmianie podglądów podrzędnych przy użyciu autolayout

83

Z miłości do Boga nie mogę zawisnąć w tym superwizji zmiany rozmiaru.

Mam UIView *superview z 4 UILabels. 2 pełnią funkcję nagłówka dla dwóch pozostałych.

Zawartość wszystkich 4 jest dynamiczna i pochodzi z bazy danych.

SizeToFitvs SizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, podając albo UILayoutFittingCompressedSizelub UILayoutFittingExpandedSize.

Używam autoukładu programowo i ustawiłem wysokość nadzoru na równą lub większą liczbę fikcyjną.

gdzie i jak używać tych SizeToFitvs sizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, podając albo UILayoutFittingCompressedSizelub UILayoutFittingExpandedSize. Przeczytałem wiele wskazówek dotyczących stosu, ale skończyło się na niczym.

CZY muszę ponownie obliczyć ograniczenia dla superwizji w konkretnym miejscu. Czy może ustawić wysokość na „@ property” w swojej klasie kontrolera, a następnie usunąć i ponownie go odczytać? Próbowałem umieścić wszystko wszędzie, a potem trochę. Nadal otrzymuję wynik końcowy tego samego rozmiaru z fikcyjną wysokością i tekstem unoszącym się na zewnątrz. Nawet po ustawieniu clipsToBound w podglądzie.

Drapię się po włosach… pomocy

Pedroinpeace
źródło
1
Hej, czy mógłbyś wysłać swój kod gdzieś na pastebin czy coś, gdybym mógł rzucić okiem? Mam podobny problem. Minął tydzień lub więcej.
esh

Odpowiedzi:

104

Jeśli używasz układu automatycznego, oto, co musisz zrobić:

  1. Upewnij się, że nie dodajesz stałych ograniczeń szerokości i / lub wysokości do żadnego z widoków podrzędnych (w zależności od wymiarów, które chcesz dynamicznie zmieniać). Chodzi o to, aby wewnętrzny rozmiar treści każdego widoku podrzędnego określał jego wysokość. UILabels są dostarczane z 4 automatycznymi niejawnymi ograniczeniami, które (z priorytetem mniejszym niż Wymagany) będą próbowały utrzymać ramkę etykiety na dokładnym rozmiarze wymaganym do zmieszczenia całego tekstu w środku.

  2. Upewnij się, że krawędzie każdej etykiety są sztywno połączone (z Wymaganymi ograniczeniami pierwszeństwa) ze sobą nawzajem i z ich nadzorem. Chcesz się upewnić, że jeśli wyobrazisz sobie, że jedna z etykiet się powiększy, zmusi to inne etykiety do zrobienia dla niej miejsca i, co najważniejsze, do rozszerzenia funkcji superview.

  3. Dodawaj ograniczenia tylko do nadzoru, aby ustawić jego pozycję, a nie rozmiar (przynajmniej nie dla wymiarów, które chcesz dynamicznie zmieniać). Pamiętaj, że jeśli poprawnie ustawisz wewnętrzne wiązania, ich rozmiar zostanie określony przez rozmiary wszystkich podglądów podrzędnych, ponieważ jego krawędzie są w jakiś sposób połączone z ich krawędziami.

Otóż ​​to. Nie musisz dzwonić sizeToFitani systemLayoutSizeFittingSize:uruchamiać tego, po prostu załaduj swoje poglądy i ustaw tekst i to powinno być na tyle. Silnik układu systemu wykona obliczenia, aby rozwiązać Twoje ograniczenia. (Jeśli już, być może będziesz musiał zadzwonić setNeedsLayoutdo nadzoru ... ale to nie powinno być wymagane).

smileyborg
źródło
Dzięki smileyborg. Spóźniona odpowiedź, ponieważ byłem w trakcie realizacji projektu i nie rozumiałem tego, o czym myślisz. Teraz miałem okazję popracować trochę więcej z ograniczeniami w programistyce, a zwłaszcza z constraintsWithVisualFormati całkowicie rozumiem twój punkt widzenia na temat rozciągania się podglądów podrzędnych i wypychania ich do rozmiaru :)
Jeszcze
Zgadzam się z rozwiązaniem, ale nie działa dla mnie, sprawdź stackoverflow.com/questions/34635838/ ...
Omer
Ta odpowiedź jest magiczna. O wiele mniej wysiłku z mojej strony, aby widoki wyglądały dobrze.
Chris
1
Należy wspomnieć, że powinieneś ustawić, translatesAutoresizingMaskIntoConstraints = NOjeśli używasz xib.
KudoCC
translatesAutoresizingMaskIntoConstraints = NO jest odpowiedzią na mój przypadek. Ale teraz widok pojemnika stracił ramkę, a jego początek jest zawsze (0,0), nie mogę go umieścić w miejscu, które chcę. stackoverflow.com/questions/45548372/ ...
karim
24

Użyj widoków kontenera

W poniższym przykładzie mam obraz 30x30 i UILabeljest mniejszy niż widok zawierający tekst zastępczy. Potrzebowałem widoku zawierającego, który był co najmniej tak duży jak obraz, ale musiał urosnąć, aby zawierał tekst wielowierszowy.

W formacie wizualnym kontener wewnętrzny wygląda następująco:

H:|-(15.0)-[image(30.0)]-(15.0)-[label]-(15.0)-|
V:|[image(30.0)]|
V:|[label(>=30.0)]|

Następnie ustaw widok zawierający pasujący do wysokości etykiety. Teraz widok zawierający dostosuje rozmiar etykiety.

Jak zauważył @smileyborg w swojej odpowiedzi, sztywne połączenie treści z superviewem informuje silnik układu, że prosty widok kontenera powinien spowodować jego wzrost.

Żółte prostokąty wyrównania

Jeśli chcesz, aby żółte prostokąty wyrównania zostały dodane -UIViewShowAlignmentRects YESdo listy argumentów uruchamiania twojego schematu.

UILabel, który jest wielowierszowy

Cameron Lowell Palmer
źródło
12
-UIViewShowAlignmentRects YES- świetna wskazówka!
Ralfonso
2
W takim przypadku pojemnik musi tylko dopasować swoją wysokość do etykiety. A jeśli kontener dostosuje się do sumy wysokości więcej niż jednego widoku?
da Rocha Pires
7

Zostało to znacznie łatwiejsze dzięki wprowadzeniu widoków stosu w systemie iOS 9. Użyj widoku stosu w widoku, aby zawrzeć całą zawartość, która zmienia rozmiar, a następnie po prostu wywołaj

view.setNeedsUpdateConstraints()
view.updateConstraintsIfNeeded()
view.setNeedsLayout()
view.layoutIfNeeded()

po zmianie treści. Następnie możesz uzyskać nowy rozmiar, dzwoniąc

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

jeśli kiedykolwiek będziesz musiał obliczyć dokładny rozmiar wymagany dla widoku.

Jacob Ruth
źródło
2
Używam StackView i dynamicznie dodam widoki, te widoki nie są zmieniane. @ JacobRuth
Mansuu ....
6

Jest to prawie zgodne z odpowiedzią @smileyborg i zawiera konkretny przykład.

wprowadź opis obrazu tutaj

Nie będzie opisywać wszystkich ograniczeń, ale te związane z obliczaniem wysokości obiektów UI.

  1. [Etykieta] Etykiety nie mogą mieć stałego heightograniczenia, w tym przypadku AutoLayout nie zmieni rozmiaru etykiet w celu dopasowania do tekstu, więc kluczem jest ustawienie ograniczeń krawędzi. (zielone strzałki)
  2. [Podgląd] Kroki 1 i 3 są bardzo łatwe do wykonania, ale ten krok może zostać źle zrozumiany. Podobnie jak w przypadku etykiet, podglądy podrzędne nie mogą mieć heightustawionych ograniczeń. Wszystkie widoki podrzędne muszą mieć topustawione ograniczenie, ignorując bottomograniczenie, co może sprawić, że myślisz, że wyzwoli niezadowalający wyjątek ograniczenia w czasie wykonywania, ale nie będzie, jeśli ustawisz bottomograniczenie dla ostatniego widoku podrzędnego. Pominięcie tego spowoduje zniszczenie układu. (Czerwone strzały)

  3. [Superview] Ustaw wszystkie ograniczenia tak, jak potrzebujesz, ale zwróć dużą uwagę na heightograniczenie. Przypisz mu losową wartość, ale ustaw ją jako opcjonalną, AutoLayout ustawi wysokość dokładnie tak, aby pasowała do podwidoków. (niebieskie strzałki)

Działa to doskonale, nie ma potrzeby wywoływania żadnych dodatkowych metod aktualizacji układu systemu.

Stefan
źródło
jak ustawić wysokość jako opcjonalną .. Jestem nowy w iOS, więc nie mogę tego rozgryźć. dzięki
Faisal Naseer