Ändern Sie die Größe der Übersicht, nachdem sich die Unteransichten mithilfe des automatischen Layouts dynamisch geändert haben

83

Ich kann aus Liebe zu Gott nicht den Dreh raus haben.

Ich habe eine UIView *superview mit 4 UILabels. 2 fungieren als Header für die 2 anderen.

Der Inhalt in allen 4 ist dynamisch und stammt aus der Datenbank.

SizeToFitvs SizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, entweder UILayoutFittingCompressedSizeoder vorbei UILayoutFittingExpandedSize.

Ich verwende Autolayout programmgesteuert und habe die Höhe der Überwachungsansicht so eingestellt, dass sie einer Dummy-Zahl entspricht oder größer ist.

wo und wie verwende ich diese SizeToFitvs sizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, entweder UILayoutFittingCompressedSizeoder UILayoutFittingExpandedSize. Ich habe hier auf Stack viele Tipps gelesen, aber am Ende nichts.

MUSS ich die Einschränkungen für die Übersicht an einem bestimmten Ort neu berechnen? Maby setzt die Höhe in seiner Controller-Klasse auf "@ property" und entfernt und liest sie? Atm Ich habe versucht, alles überall und noch mehr zu platzieren. Trotzdem erhalte ich das gleiche Endergebnis, wenn die Dummy-Höhe und der Text nach außen schweben. Auch nach dem Setzen von clipsToBound in der Unteransicht.

Ich kratzte mir die Haare von ... Hilfe

Pedroinpeace
quelle
1
Hey, könntest du deinen Code irgendwo auf Pastebin posten oder so, wenn ich einen Blick darauf werfen könnte? Ich leide an einem ähnlichen Problem. Es ist eine Woche oder länger her.
Esh

Antworten:

104

Wenn Sie das automatische Layout verwenden, müssen Sie Folgendes tun:

  1. Stellen Sie sicher, dass Sie keiner Ihrer Unteransichten feste Breiten- und / oder Höhenbeschränkungen hinzufügen (abhängig davon, welche Dimension (en) Sie dynamisch anpassen möchten). Die Idee ist, die intrinsische Inhaltsgröße jeder Unteransicht die Höhe der Unteransicht bestimmen zu lassen. UILabels werden mit 4 automatischen impliziten Einschränkungen geliefert, die (mit weniger als der erforderlichen Priorität) versuchen, den Rahmen des Etiketts auf der exakten Größe zu halten, die erforderlich ist, um den gesamten Text darin aufzunehmen.

  2. Stellen Sie sicher, dass die Kanten jedes Etiketts fest (mit Einschränkungen für die erforderliche Priorität) mit den Kanten voneinander und ihrer Übersicht verbunden sind. Sie möchten sicherstellen, dass, wenn Sie sich vorstellen, dass eines der Labels größer wird, dies die anderen Labels dazu zwingt, Platz dafür zu schaffen, und vor allem, dass die Übersicht ebenfalls erweitert wird.

  3. Fügen Sie der Übersicht nur Einschränkungen hinzu, um ihre Position und nicht ihre Größe festzulegen (zumindest nicht für die Dimension (en), deren Größe dynamisch sein soll). Denken Sie daran, dass bei korrekter Einrichtung der internen Einschränkungen die Größe durch die Größe aller Unteransichten bestimmt wird, da die Kanten in gewisser Weise mit ihren verbunden sind.

Das ist es. Sie müssen nicht anrufen sizeToFitoder systemLayoutSizeFittingSize:dies zum Laufen bringen, laden Sie einfach Ihre Ansichten und legen Sie den Text fest, und das sollte es sein. Die Systemlayout-Engine führt die Berechnungen für Sie durch, um Ihre Einschränkungen zu lösen. (Wenn überhaupt, müssen Sie möglicherweise setNeedsLayoutdie Übersicht aufrufen ... dies sollte jedoch nicht erforderlich sein.)

Smileyborg
quelle
Danke smileyborg. Eine späte Antwort, da ich mitten in einem Projekt war und nicht ganz verstanden habe, was Sie erwähnen. Jetzt hatte ich die Möglichkeit, programmatisch und insbesondere mit Einschränkungen weiter zu arbeiten, constraintsWithVisualFormatund ich verstehe Ihre Meinung zu den enthaltenen Unteransichten, die sich dehnen und die Übersicht auf ihre Größe verschieben :)
Nochmals vielen
Ich bin mit der Lösung einverstanden, aber sie funktioniert bei mir nicht. Überprüfen Sie stackoverflow.com/questions/34635838/…
Omer
Diese Antwort ist magisch. So viel weniger Aufwand meinerseits, damit die Aussichten gut aussehen.
Chris
1
Es sollte erwähnt werden, dass Sie festlegen sollten, translatesAutoresizingMaskIntoConstraints = NOob Sie xib verwenden.
KudoCC
translatesAutoresizingMaskIntoConstraints = NO ist die Antwort für meinen Fall. Aber jetzt hat die Containeransicht den Frame verloren und ihr Ursprung ist immer (0,0). Ich kann ihn nicht an die gewünschte Stelle setzen. stackoverflow.com/questions/45548372/...
karim
24

Verwenden Sie Containeransichten

Im folgenden Beispiel habe ich ein 30x30-Bild und das UILabelist kleiner als die enthaltende Ansicht mit dem Platzhaltertext. Ich brauchte, dass die enthaltende Ansicht mindestens so groß wie das Bild war, aber sie musste vergrößert werden, um mehrzeiligen Text zu enthalten.

Im visuellen Format sieht der innere Container folgendermaßen aus:

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

Stellen Sie dann die enthaltende Ansicht so ein, dass sie der Höhe des Etiketts entspricht. Jetzt enthält die enthaltende Ansicht die Größe des Etiketts.

Wie @smileyborg in seiner Antwort hervorhob, informiert das starre Verbinden des Inhalts mit der Übersicht die Layout-Engine darüber, dass die einfache Containeransicht dazu führen sollte, dass er wächst.

Gelbe Ausrichtungsrechtecke

Wenn Sie möchten, dass die gelben Ausrichtungsrechtecke -UIViewShowAlignmentRects YESin die Liste der Ausführungsargumente Ihres Schemas aufgenommen werden.

UILabel, das mehrzeilig ist

Cameron Lowell Palmer
quelle
12
-UIViewShowAlignmentRects YES- toller Tipp!
Ralfonso
2
In diesem Fall muss der Container nur seine Höhe an das Etikett anpassen. Was ist, wenn sich der Container an die Summe der Höhen von mehr als einer Ansicht anpassen soll?
da Rocha Pires
7

Dies wurde durch die Einführung von Stapelansichten in iOS 9 erheblich vereinfacht. Verwenden Sie eine Stapelansicht in Ihrer Ansicht, um alle Inhalte zu enthalten, deren Größe geändert wird, und rufen Sie dann einfach auf

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

nach dem Ändern Ihres Inhalts. Dann können Sie Ihre neue Größe erhalten, indem Sie anrufen

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

Wenn Sie jemals die genaue Größe berechnen müssen, die für eine Ansicht erforderlich ist.

Jacob Ruth
quelle
2
Ich verwende StackView und füge Ansichten dynamisch hinzu. Die Größe dieser Ansichten wird nicht geändert. @ JacobRuth
Mansuu ....
5

Dies folgt fast der Antwort von @smileyborg und enthält ein konkretes Beispiel.

Geben Sie hier die Bildbeschreibung ein

Beschreibt nicht alle Einschränkungen, sondern diejenigen, die sich auf die Berechnung der Höhe von UI-Objekten beziehen.

  1. [ Beschriftung ] Beschriftungen dürfen keine feste heightEinschränkung haben. In diesem Fall ändert AutoLayout die Größe der Beschriftungen nicht an den Text. Daher ist das Festlegen von Kantenbeschränkungen der Schlüssel. (grüne Pfeile)
  2. [Unteransicht] Die Schritte 1 und 3 sind sehr einfach zu befolgen, aber dieser Schritt kann missverstanden werden. Wie bei Beschriftungen dürfen für Unteransichten keine heightEinschränkungen festgelegt sein. Für alle Unteransichten muss eine topEinschränkung festgelegt sein, wobei die bottomEinschränkung ignoriert wird. Dies kann zu der Annahme führen , dass zur Laufzeit eine nicht bottomerfüllte Einschränkungsausnahme ausgelöst wird. Dies ist jedoch nicht der Fall, wenn Sie eine Einschränkung für die letzte Unteransicht festlegen. Wenn Sie dies nicht tun, wird das Layout zerstört. (rote Pfeile)

  3. [Übersicht] Stellen Sie alle Einschränkungen so ein, wie Sie es benötigen, aber achten Sie besonders auf die heightEinschränkung. Weisen Sie ihm einen zufälligen Wert zu, machen Sie ihn jedoch optional. AutoLayout stellt die Höhe genau so ein, dass sie zu den Unteransichten passt. (blaue Pfeile)

Dies funktioniert einwandfrei, es müssen keine zusätzlichen Methoden zur Aktualisierung des Systemlayouts aufgerufen werden.

Stefan
quelle