UIScrollView verwendet keine Autolayout-Einschränkungen

78

Ich habe eine Bildlaufansicht und eine Bildansicht dahinter und fülle sie mit Schreibfedern. Ich benutze Autolayout. Ich habe einen unteren Bereich zum Überwachen und einen oberen Bereich zum Überwachen beider Ansichten. Die Bildansicht macht genau das, was ich will. Für das iPhone 5 ist es dort, wo ich es will. Bei den anderen iPhones bleibt es über dem unteren Bildschirmrand, sodass die Größe korrekt angepasst wird. Die Bildlaufansicht sieht auf dem iPhone 5 richtig aus, auf den anderen Handys wird die Größe jedoch nicht geändert, sodass ein Bildlauf unter der Ansicht der App nach unten erfolgt. Ich erhalte folgende Meldungen im Protokoll:

 2012-11-21 10:42:38.576 LCHApp[12604:907] 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:0x1d8ea080 UIScrollView:0x1d8413b0.bottom == UIImageView:0x1d892110.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x1d8cca10 h=-&- v=-&- ScheduleViewNib:0x1d853630.height == UIScrollView:0x1d8413b0.height - 386>",
"<NSLayoutConstraint:0x1d8e5340 V:[UIImageView:0x1d892110]-(64)-|   (Names: '|':ScheduleView:0x1d8efc30 )>",
"<NSAutoresizingMaskLayoutConstraint:0x1d8cf520 h=--& v=--& V:[ScheduleView:0x1d8efc30(480)]>",
"<NSLayoutConstraint:0x1d8eaed0 V:|-(45)-[UIScrollView:0x1d8413b0]   (Names: '|':ScheduleView:0x1d8efc30 )>"


 Will attempt to recover by breaking constraint 
 <NSLayoutConstraint:0x1d8ea080 UIScrollView:0x1d8413b0.bottom ==      UIImageView:0x1d892110.bottom>

Ich habe es schon versucht

[self setTranslatesAutoresizingMaskIntoConstraints:YES];

und

[self.myScrollView setTranslatesAutoresizingMaskIntoConstraints:YES];

Soweit ich sehen kann, werden dadurch alle Einschränkungen aus den Ansichten entfernt. Und ist nicht das, was ich will.

Sir RupertIII
quelle
2
Apples technischer Hinweis TN2154: UIScrollView und Autolayout behandelt dieses Problem ausführlich.
Smileyborg

Antworten:

176

Die Beziehung zwischen UIScrollView und automatischem Layout unterscheidet sich von anderen Aspekten des automatischen Layouts. Grundsätzlich würde nichts scrollen, wenn das einfache automatische Layout funktionieren würde. Wenn beispielsweise eine Unteransicht der Bildlaufansicht auf normale Weise durch eine Einschränkung auf 10 Punkte vom oberen Rand der Bildlaufansicht fixiert würde, wäre sie dort absolut fixiert. es würde sich niemals bewegen, egal wie die Bildlaufansicht gescrollt wurde.

Um dieses Problem zu lösen, arbeitet eine UIScrollView, die Autolayout verwendet, auf völlig neue Weise. Wenn Sie also "Ich verwende Autolayout" sagen, müssen Sie sich darauf vorbereiten, dass die Dinge ganz anders funktionieren als zuvor. Sie müssen entweder eine einzelne Unteransicht der Bildlaufansicht mit translatesAutoresizingMaskIntoConstraints = YESund eine explizite Inhaltsgröße verwenden, oder alles muss vorhanden sein, translatesAutoresizingMaskIntoConstraints = NOund die Inhaltsgröße wird implizit basierend auf den Einschränkungen der Unteransichten abgeleitet.

Dies wird in https://developer.apple.com/library/content/releasenotes/General/RN-iOSSDK-6_0/index.html sehr gut erklärt

matt
quelle
5
Diese Frage könnte Sie interessieren: stackoverflow.com/questions/14307037/… (nicht zuletzt wegen der Prämie!) Ich denke, dies ist ein Scrollview / Autolayout-Problem, aber meiner Meinung nach liest es sich wie ein Fehler - in diesem Fall die Scroll Ansicht ist eine Tabellenansicht, und die Inhaltsgröße wird beim Drehen nicht richtig angepasst.
Jrturton
3
@matt Ich weiß nicht, ob Sie dieses Verhalten gesehen haben, aber wenn Sie nur Layouteinschränkungen verwenden, um die Inhaltsgröße einer Bildlaufansicht zu definieren, gibt es einen Fehler: Scrollen Sie den Inhaltsversatz von (0, 0) weg und verschieben Sie ihn auf eine andere Registerkarte oder Modal View Controller, kommen Sie zurück und die Unteransichten der Bildlaufansicht werden alle um den Inhaltsversatz verschoben, und Sie können nicht zurückkehren. Ich wäre dankbar, wenn Sie dies bestätigen und mein Radar täuschen
könnten
3
@ edelaney05 Ich denke, ich kann den Fehler bestätigen, aber bevor Sie ihn an Apple senden, sollten Sie ein Demo-Projekt erstellen, insb. da das Kopieren und Einfügen von Code in openradar.appspot.com/radar?id=2932404 nicht einmal kompiliert werden kann (Sie haben den Namen constraintsWithVisualFormat:options:metrics:views:falsch eingegeben ). Verwenden Sie immer echten Code, der tatsächlich funktioniert. Außerdem können Sie in ein reales Projekt ein tatsächliches Bild einfügen. Die Apple-Leute haben keine Vorstellungskraft und keine Zeit; Sie müssen die ganze Arbeit für sie im Voraus erledigen.
Matt
3
@ edelaney05 "Schulter Consectetur Pancetta" ???? :) OK gut. Ich habe tatsächlich eine viel genauere basierend auf ihrem Code gemacht, mit einer Bildansicht, die auf ein großes Bild zugeschnitten ist. Indem die Bildlaufansicht eine rote Hintergrundfarbe erhielt und protokolliert wurde, wurde sehr deutlich, dass die Bildlaufansicht alles für richtig hielt (Inhaltsgröße, Inhaltsversatz), aber die Bildansicht an der falschen Stelle zeichnete, dh um den Betrag versetzt des Inhaltsversatzes von dem Zeitpunkt an, an dem wir die Ansicht verlassen haben.
Matt
2
@matt baconipsum.com ! :-) Genial. Genau das gleiche Verhalten, das ich gesehen habe. Die Bildlaufansicht meldete alles als "normal", aber das Zeichnen war um einen Faktor des Versatzes falsch. Vielen Dank für die Bestätigung, dass ich nicht verrückt bin (aber nur in Bezug auf diesen Fehler!).
edelaney05
162

Sehr wichtig bei Verwendung des automatischen Layouts: Sie müssen den rechten und / oder unteren Rand der letzten Unteransicht rechts und / oder den unteren Rand der Bildlaufansicht anheften. Auf diese Weise erkennt die Bildlaufansicht die Inhaltsgröße. Zum Beispiel:

[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:lastSubView
                                                 attribute:NSLayoutAttributeRight
                                                 relatedBy:NSLayoutRelationEqual
                                                    toItem:scrollView
                                                 attribute:NSLayoutAttributeRight
                                                multiplier:1.0
                                                  constant:0]];

Ich danke dieser Seite für das perfekte Beispiel.

Ich habe dadurch Stunden verloren und hoffe, anderen meinen Schmerz zu ersparen.

Phatmann
quelle
4
Dies ist perfekt. Ich habe nach einem einfachen Beispiel wie dem im Link gesucht. Vielen Dank!!!
pgpb.padilla
Während Mats Antwort gut ist, ist diese viel praktischer hilfreich, um die Probleme zu lösen, die ich mit ihrer Verwendung hatte
am
22
@dmur "Während Mats Antwort gut ist, ist diese viel praktischer hilfreich" - Alter, das ist auch meine Antwort. Er hat den Code / die Erklärung aus meinem Buch bekommen! Ich bin froh, dass ich zweimal helfen konnte. :)))
Matt
Abhängig davon, wie Sie Ihre scrollView und ihre Unteransichten anordnen, müssen Sie Ihre Inhalte möglicherweise links oder oben anheften. In meinem Fall musste ich alles links anheften.
ArtSabintsev
Sie können die Einschränkung auch über den Interface Builder hinzufügen. Gute Antwort!
Moisés Olmedo
0

Damit UIScrollviews mit Einschränkungen gut funktionieren, verwende ich diesen hier beantworteten Ansatz . In dieser Antwort gehe ich darauf ein, wie eine vertikal scrollende Bildlaufansicht funktioniert, die auch mit Gerätedrehung funktioniert. Sie können den Ansatz optimieren, um auch mit horizontal scrollenden Bildlaufansichten zu arbeiten. Fügen Sie für Bildlaufansichten, die in beide Richtungen scrollen, nicht den Trick zur Größenanpassung der Breitenbeschränkung hinzu. Aber mach alles andere gleich.

n8tr
quelle
-3

Einige Sachen.

  1. Stellen Sie sicher, dass das automatische Layout aktiviert ist (IB auf der Registerkarte "Dateiinspektor").
  2. Stellen Sie sicher, dass Sie KEINE Änderungen vornehmen, die Grenzen, Rahmen usw. betreffen - dies alles wird jetzt durch automatische Einschränkungen durchgeführt
  3. Stellen Sie sicher, dass Sie sich von AutoResizingMask fernhalten. Dies wird mit Ihren neuen Einstellungen konkurrieren. Wenn dies richtig gemacht wird, können Sie Ihre Schaltfläche jetzt gestalten und es wird großartig funktionieren. Hier ist wie.

Dieser Fehler besagt, dass entweder Ihre Feder oder ein Steuerelement in dieser Feder NICHT das automatische Layout verwendet.

JustLearningAgain
quelle
1
Aber UIScrollView ist etwas Besonderes, und Ihre Antwort berücksichtigt diese Tatsache nicht.
Matt