Wie kann ich Autolayout verwenden, um Einschränkungen für meine UIScrollview festzulegen?

176

Ich habe zwei Tage damit verbracht, die verschiedenen Lösungen für auszuprobieren gemischte und reine Autolayout-Ansätze auszuprobieren , um ein triviales Scrollview-Setup vor dem Autolayout zu erreichen, und es ist jetzt offiziell - ich muss zu dumm sein. Ich richte dies hauptsächlich im Storyboard ein (nun, es ist einfach so wie es ist).

Hier ist meine Bitte um Hilfe.

Ansichtsbaum:

UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton

Die Tasten sollen horizontal scrollen (von links nach rechts und umgekehrt). Kann jemand bitte mitteilen, wie die Einschränkungen festgelegt werden sollen, um dies mit reinem Autolayout zu erreichen?

- -

Ich habe den gemischten Ansatz so ausprobiert:

UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton

... und Festlegen von Einschränkungen für Breite und Höhe für die contentviewund dietranslatesAutoresizingMaskIntoConstraints Einstellungen gemäß Apples TechNote. Die Schaltflächen und die Bildlaufansicht werden mithilfe von Einschränkungen eingerichtet. Dadurch wird die Bildlaufansicht gescrollt (yay), aber leider wird zu weit gescrollt! Soweit ich das beurteilen kann, hat sich die Bildlaufbreite gegenüber dem, auf den ich die Inhaltsansicht eingestellt habe, irgendwie verdoppelt ??? !!! ???

Ich habe auch den reinen Autolayout-Ansatz ausprobiert, sowohl mit contentviewals auch ohne. Alle Ansichten sind translatesAutoresizingMaskIntoConstraints=NO, außer self.view. Die Schaltflächen haben feste Breiten- / Höhenbeschränkungen und sind an allen vier Kanten der Bildlaufansicht befestigt. Nichts rollt.

Ich bin total verblüfft, warum ich es nicht richtig zum Laufen bringen kann. Jede Hilfe wird sehr geschätzt, und wenn Sie weitere Informationen benötigen, fragen Sie bitte!

AKTUALISIERTER Screenshot mit Lösung - buttonZ Einschränkungen:

Geben Sie hier die Bildbeschreibung ein

EDIT @ Jamie Forrest Die Lösung stellt sich also als die falsche nachfolgende Einschränkung für die letzte Schaltfläche heraus. Anstelle von 6441 war der Wert, den ich eingestellt hatte, negativ, -6441. Das Schwierige ist, dass beim Festlegen des Werts im Storyboard zwei Optionen in der Pin-Symbolleiste angezeigt werden:

Geben Sie hier die Bildbeschreibung ein

Der aktuelle Canvas-Wert ist negativ (führt zu keinem Bildlauf), und die folgende Option ist positiv (Bildlauf aktivieren). Das heißt, ich bin nicht dumm, aber zumindest halb blind, denke ich. Obwohl es zu meiner Verteidigung nicht etwas störend ist, dass XCode keinen Fehler für die "falsche" Einstellung anzeigt?

WIEDER BEARBEITET Nun, das ist lustig ... Ändern des nachgestellten Werts von -6441 (kein Bildlauf) auf 6441 aktiviertes Bildlauf. Aber mein alter Freund, die "zu große Inhaltsgröße", war zurück, was zu einer Inhaltsgröße führte, die doppelt so groß war, wie sie sein sollte! Die Lösung, um den richtigen Bildlauf für den Inhalt zu erhalten, bestand darin, die nachfolgende Einschränkung auf NULL zu setzen! Dies ist nicht offensichtlich, wenn Sie in Storyboard arbeiten, aber wenn Sie sich den Code von @Infinity James ansehen, ist es genau das, was es sein sollte.

user1459524
quelle
Wo berechnen / legen Sie die Inhaltsgröße für Ihre Bildlaufansicht fest? In Bezug auf Ihren ersten Versuch mit einer ContentView haben Sie gesagt, dass sie zu weit scrollt.
Tim
2
Soweit ich weiß, kann man das nicht festgelegt contentSizeeines UIScrollViewnur mit Auto - Layout. Und es ist das contentSize, was definiert, wie viel Sie scrollen können. Sie müssen dies also irgendwann irgendwo manuell einstellen. Im Übrigen können Sie Layoutbeschränkungen verwenden, um Ansichtsrahmen relativ zueinander einzurichten.
Guillaume
@ Jeff, die Inhaltsgröße ist fest, sie ändert sich nie. Ich habe die Inhaltsgröße im Storyboard festgelegt, indem ich die richtige Höhe und Breite für die Inhaltsansicht manuell eingegeben habe, und ich habe die Höhe und Breite mit Einschränkungen im Storyboard verknüpft.
user1459524
Drucken Sie Ihre contentSize zur Laufzeit aus und prüfen Sie, ob sie mit den von Ihnen eingegebenen Werten übereinstimmt. Die contentSize bestimmt, wie viel Bildlauf ausgeführt wird. Das Problem bei Ihrem ersten Versuch besteht also darin, die contentSize zu verwenden.
Tim
@ Guillaume, also ist der "pure Autolayout" -Ansatz doch nicht so rein? Aber wie stelle ich die contentSize manuell ein? Wie oben erwähnt, setze ich die Höhe / Breite der Inhaltsansicht auf feste Werte (im Storyboard). Aber es rollt zu weit (2x).
user1459524

Antworten:

68

Es ist schwierig, die genauen Werte und Einstellungen Ihrer Einschränkungen zu erkennen, wenn Sie sie hier eingefügt haben. Daher bin ich mir nicht sicher, ob Sie sich Ihre Screenshots ansehen, in denen Sie einen Fehler gemacht haben.

Anstelle einer Erklärung, was in Ihrem Setup nicht stimmt, habe ich ein grundlegendes Beispielprojekt mit einer sehr ähnlichen Ansichtshierarchie und Einschränkungskonfiguration wie die von Ihnen beschriebene erstellt. Das horizontale Scrollen funktioniert wie erwartet im Beispielprojekt, das den von Apple im Technischen Hinweis beschriebenen Ansatz "Pure AutoLayout" verwendet .

Ich hatte auch große Probleme damit, Auto Layout zum Laufen zu bringen UIScrollView. Der Schlüssel, damit es funktioniert, besteht darin, sicherzustellen, dass alle Elemente in der Bildlaufansicht zusammengenommen Einschränkungen aufweisen, die schließlich mit allen Seiten der Bildlaufansicht verknüpft sind und dazu beitragen, dass das AutoLayout-System eine Inhaltsgröße für das Bild bestimmen kann Bildlaufansicht, die größer als der Rahmen ist. Es sieht so aus, als hätten Sie versucht, dies in Ihrem Code zu tun, aber vielleicht hatten Sie einige überflüssige Einschränkungen, die die contentSize zu klein machten.

Wie bereits erwähnt, können Sie mit AutoLayout und UIScrollview die contentSize nicht mehr explizit festlegen. Das AutoLayout-System berechnet die contentSize basierend auf Ihren Einschränkungen.

Ich fand dieses E-Book-Kapitel auch sehr hilfreich, um zu verstehen, wie das alles funktioniert. Hoffe das alles hilft.

Jamie Forrest
quelle
2
DANKE für das Beispielprojekt! Es funktioniert, und als ich es durchgesehen habe, konnte ich zunächst keinen Unterschied zu meinem Projekt feststellen! Ich habe die Ansichten in mein Projekt kopiert und dabei eine andere Einstellung als Einschränkungen vermutet, aber es hat weiterhin funktioniert. Dies führte mich zu der Feststellung, dass die nachfolgende Einschränkung für die letzte Schaltfläche in meinem Projekt negativ ist - davor, während Ihre einen positiven Wert hat! Durch Ändern von - auf positiv wurde der Bildlauf aktiviert! Wenn ich die Pin-Symbolleiste aufrufe, gibt es zwei Möglichkeiten: Aktuellen Canvas-Wert verwenden, der negativ ist, und Bildlaufansicht (aktuellen Wert verwenden), der positiv ist ...?!
user1459524
Ah ja. Der negative Wert würde tatsächlich die Inhaltsgröße der Bildlaufansicht verkleinern, um der Tatsache zu entsprechen, dass die Hinterkante enden sollte, bevor die Schaltfläche endet. Ich bin froh, dass das Beispielprojekt geholfen hat!
Jamie Forrest
Es hat viel getan. Schauen Sie sich meine aktualisierte Antwort an. Der nachfolgende Wert sollte anscheinend tatsächlich 0 (Null) sein.
user1459524
6
Das ist traurig, dass wir Screenshots anstelle von Code teilen müssen. Das liegt nur daran, dass Apple Entwickler dazu ermutigt, Builder zu verwenden, anstatt eine bessere API bereitzustellen.
Vladimír Slavík
4
Völlig unintuitiv. Entwickler müssen Stunden und Stunden verschwenden, um herauszufinden, was in den Köpfen der XCode-Entwickler vor sich ging.
Josh
49

LOL Willkommen im Dummheitsclub. Ich bin einer der Gründer. : D.

Für das VERTIKALE Scrollen : Die einzige Möglichkeit, es zum Laufen zu bringen (iOS 8, Xcode 6 und reines Autolayout), bestand darin, meiner Bildlaufansicht die folgenden Einschränkungen hinzuzufügen (alle in Bezug auf die Übersicht):

  • Gleiche Breiten
  • Gleiche Höhen
  • Mitte Y-Ausrichtung
  • Center X-Ausrichtung

Meine Struktur:

  UIView
   - ScrollView
    - Subview
    - Subview
    - Subview
    - Subview
    - ...

Dies ist das Endergebnis:

Demo

Dies ist das Setup:

Konfiguration Ganzer Bildschirm

Und hier ist das Projekt .

Hoffentlich würde dies jemanden davor bewahren, um 5 Uhr morgens zu schlafen. : D.

Backslash-f
quelle
Vielen Dank für die Hilfe! Wie haben Sie die Unteransicht vom Typ "Unteransicht" erhalten? Ich schaue mir Ihr Projekt in Xcode 6.2 an und es nennt diese kleinen Rechtecke "Unteransicht" mit der einzigen Einschränkung, dass es 63px hoch ist.
Andrew K
1
Schöne Grüße! Diese "Unteransicht" ist eigentlich eine UIVIew. Das ist nur ein Name ... Sie können dort alles eingeben. Schauen Sie sich dieses Bild an: cl.ly/image/291f1K2N0V3p Beim Thema "Einschränkung" haben die Unteransichten mehr als nur eine Höhenbeschränkung. Überprüfen Sie die gesamte Einschränkungsliste für diese Ansichten hier: cl.ly/image/3l061i123j2i
backslash-f
1
Ich kann das Scrollen immer noch nicht zum Laufen bringen. Ich habe festgestellt, dass Ihre Unteransichten in Ihrem Projekt "ausgegraut" sind. Nach einigen Recherchen sieht es so aus, als würden Sie "Größenklassen" verwenden. Wie wirkt sich das auf das Scrollen aus? Gibt es eine Möglichkeit, das Scrollen zum Laufen zu bringen, ohne dies zu verwenden?
Andrew K
Wie haben Sie Ihre Übersicht so viel länger als die Standardlänge gemacht? Ich versuche, Schaltflächen hinzuzufügen, die "unter der Falte" (oder außerhalb des Bildschirms) angezeigt werden, aber natürlich kann ich sie nicht zur Übersicht hinzufügen, wenn ich sie nicht per Drag & Drop auf die Übersicht ziehen kann, da sie nicht groß genug ist.
Andrew K
1
Nach einem langen Tag des Suchens und Versuchs, dieses Dummheitslayout zu erstellen, fand ich diese Antwort und arbeitete beim ersten Versuch. Danke Mann. Sie retten meinen Tag. Ich wünschte, ich könnte tausend Stimmen für diese Antwort abgeben. )
Bobby Stenly
32

Einfaches Beispiel in sich geschlossen

Gemessen an der hohen Anzahl von Stimmen zu der Frage und der niedrigen Anzahl von Stimmen zu den Antworten finden die Menschen hier keine verständliche und schnelle Lösung. Lassen Sie mich versuchen, eine hinzuzufügen. Dieses Projekt ist ein in sich geschlossenes Beispiel, das vollständig im Interface Builder erstellt wurde. Sie sollten in der Lage sein, es in 10 Minuten oder weniger durchzuarbeiten. Anschließend können Sie die erlernten Konzepte auf Ihr eigenes Projekt anwenden.

Geben Sie hier die Bildbeschreibung ein

In der ursprünglichen Frage wird nach Bildlaufschaltflächen gefragt. Hier benutze ich nurUIView s, aber sie können jede Ansicht darstellen, die Sie mögen. Ich habe mich auch für das horizontale Scrollen entschieden, da die Storyboard-Screenshots für dieses Format kompakter sind. Die Prinzipien für das vertikale Scrollen sind jedoch dieselben.

Schlüssel Konzepte

  • Das UIScrollView sollte nur eine Unteransicht verwenden. Dies ist eine 'UIView', die als Inhaltsansicht dient und alles enthält, was Sie scrollen möchten.
  • Machen Sie die Inhaltsansicht und die übergeordnete Ansicht der Bildlaufansicht Element der Bildlaufansicht für das horizontale Scrollen die gleichen Höhen haben. (Gleiche Breite für vertikales Scrollen)
  • Stellen Sie sicher, dass der gesamte scrollbare Inhalt eine festgelegte Breite hat und allseitig fixiert ist.

Starten Sie ein neues Projekt

Es kann sich nur um eine Einzelansicht handeln.

Storyboard

In diesem Beispiel erstellen wir eine horizontale Bildlaufansicht. Wählen Sie den View Controller und dann im Größeninspektor Freiform aus. Machen Sie die Breite 1,000und die Höhe 300. Dies gibt uns nur Platz im Storyboard, um Inhalte hinzuzufügen, die gescrollt werden.

Geben Sie hier die Bildbeschreibung ein

Fügen Sie eine Bildlaufansicht hinzu

Fügen Sie ein hinzu UIScrollViewund stecken Sie alle vier Seiten in die Stammansicht des Ansichtscontrollers.

Geben Sie hier die Bildbeschreibung ein

Fügen Sie eine Inhaltsansicht hinzu

Fügen Sie der UIViewBildlaufansicht eine als Unteransicht hinzu. Das ist der Schlüssel. Versuchen Sie nicht, der Bildlaufansicht viele Unteransichten hinzuzufügen. Fügen Sie einfach eine einzelne hinzu UIView. Dies ist Ihre Inhaltsansicht für die anderen Ansichten, die Sie scrollen möchten. Befestigen Sie die Inhaltsansicht an allen vier Seiten an der Bildlaufansicht.

Geben Sie hier die Bildbeschreibung ein

Gleiche Höhen

CommandKlicken Sie nun in der Dokumentübersicht sowohl auf die Inhaltsansicht als auch auf die übergeordnete Ansicht der Bildlaufansicht, um beide auszuwählen. Stellen Sie dann die Höhen gleich ein ( Controlziehen Sie von der Inhaltsansicht in die Bildlaufansicht). Dies ist auch der Schlüssel. Da wir horizontal scrollen, weiß die Inhaltsansicht der Bildlaufansicht nicht, wie hoch sie sein soll, es sei denn, wir stellen sie auf diese Weise ein.

Geben Sie hier die Bildbeschreibung ein

Hinweis:

  • Wenn wir den Inhalt vertikal scrollen lassen würden, würden wir die Breite der Inhaltsansicht so einstellen, dass sie der Breite der übergeordneten Elemente der Bildlaufansicht entspricht.

Inhalt hinzufügen

Addiere drei UIViews und gib ihnen alle Einschränkungen. Ich habe für alles 8-Punkte-Ränder verwendet.

Geben Sie hier die Bildbeschreibung ein

Einschränkungen:

  • Grüne Ansicht: Stecken Sie die oberen, linken und unteren Kanten fest. Machen Sie die Breite 400.
  • Rote Ansicht: Stecken Sie die oberen, linken und unteren Kanten fest. Machen Sie die Breite 300.
  • Lila Ansicht: Stecken Sie alle vier Kanten der Kanten fest. Stellen Sie die Breite unabhängig vom verbleibenden Platz ein (in diesem Fall 268).

Das Festlegen der Breitenbeschränkungen ist ebenfalls wichtig, damit die Bildlaufansicht weiß, wie breit die Inhaltsansicht sein wird.

Fertig

Das ist alles. Sie können Ihr Projekt jetzt ausführen. Es sollte sich wie das Bildlaufbild oben in dieser Antwort verhalten.

Tauschen Sie für vertikales Scrollen einfach alle Breiten- und Höhenrichtungen in diesem Beispiel aus (getestet und funktionsfähig).

Weitere Studie

Suragch
quelle
9

Die contentSize wird implizit festgelegt, indem die Einschränkungen in UIScrollView angewendet werden.

Wenn Sie beispielsweise eine UIScrollView in einer UIView haben, sieht diese folgendermaßen aus (wie Sie sicher wissen):

    UIView *containerView               = [[UIView alloc] init];
    UIScrollView *scrollView            = [[UIScrollView alloc] init];
    [containerView addSubview:scrollView];
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.translatesAutoresizingMaskIntoConstraints    = NO;
    NSDictionary *viewsDictionary       = NSDictionaryOfVariableBindings(containerView, scrollView);

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
                                                                            views:viewsDictionary]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil

Dadurch wird die scrollView so eingestellt, dass sie die Größe der containerView ausfüllt (daher muss die containerView eine bestimmte Größe haben).

Sie können dann die Inhaltsgröße von UIScrollView anpassen, indem Sie implizit festlegen, dass sie groß genug ist, um die Schaltflächen wie folgt zu halten:

    UIButton *buttonA                   = [[UIButton alloc] init];
    UIButton *buttonB                   = [[UIButton alloc] init];
    UIButton *buttonC                   = [[UIButton alloc] init];
    [scrollView addSubview:buttonA];
    [scrollView addSubview:buttonB];
    [scrollView addSubview:buttonC];
    buttonA.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonB.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonC.translatesAutoresizingMaskIntoConstraints       = NO;

    viewsDictionary                     = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);

    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonA]-|"
                                                                       options:kNilOptions
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[buttonA]-[buttonB]-[buttonC]-|"
                                                                       options:NSLayoutFormatAlignAllBaseline
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
Unendlichkeit James
quelle
Also habe ich die Einschränkungen zwischen der scrollView und den Schaltflächen festgelegt und nicht zwischen der containerView und den Schaltflächen? Ich denke, das ist der einzige Unterschied, den ich zwischen Ihrem Code und dem, was ich gerade über das Storyboard mache, mache.
user1459524
Erst nach der zweiten Lesung wurde mir klar, dass Sie eine CONTAINERview und keine CONTENTview einrichten. Basierend auf Ihrem Code habe ich alles genau im Storyboard neu erstellt und es wird nicht gescrollt. Ich werde meine Frage mit einigen Screenshots bearbeiten.
user1459524
1
Es stellte sich also heraus, dass mein Versuch, den Code im Storyboard neu zu erstellen, nicht 100% korrekt war. Der nachfolgende Wert für die letzte Schaltfläche sollte genau Null sein und H: | - [Schaltfläche A] - [Schaltfläche B] - [Schaltfläche C] - | widerspiegeln Das ist nicht sehr offensichtlich, wenn ich im Storyboard arbeite (oder zumindest nicht für mich), aber jetzt, nachdem die Tatsache trivial erscheint. Ich liebe Autolayout, aber diese kleinen Dinge bekommen dich ...
user1459524
Was @ user1459524 erwähnte, war ein Problem für mich. Meine Ansicht von unten war eine Schaltfläche und die untere Einschränkung war -32 von IB. Ich habe das auf 0 gesetzt und es wurde in IB aktualisiert, um Bottom Space zu sein: Übersicht. Es wird funktionieren, es scheint auch, solange Sie auf der positiven Seite sind, dass es funktioniert. Sieht so aus, als wäre das ein Fehler bei IB. Hoffe das hilft jemand anderem. Ich habe auch alle Ansichten entfernt und neu verkabelt, was beim Versuch, diese zu finden, hilfreich ist und normalerweise nicht lange dauert.
Michael
8

Es gibt so viele Fragen zur Verwendung von AutoLayout mit UIScrollView. Der wichtigste Punkt, den wir ignorieren, ist, dass die inneren Ansichten von UIScrollView Einschränkungen für die Inhaltsansicht , nicht jedoch für die UIScrollView selbst darstellen. Weitere Informationen finden Sie im Technischen Hinweis TN2154 :

Die UIScrollView-Klasse scrollt ihren Inhalt, indem sie den Ursprung ihrer Grenzen ändert. Damit dies mit dem automatischen Layout funktioniert, bedeuten die oberen, linken, unteren und rechten Kanten in einer Bildlaufansicht jetzt die Kanten der Inhaltsansicht.

Die folgende Abbildung zeigt Folgendes: Geben Sie hier die Bildbeschreibung ein

Sie können feststellen, dass der nachfolgende Speicherplatz 500 Punkte beträgt. Wenn die Einschränkung für UIScrollView vorgenommen wird, wird die Ansicht falsch platziert und sollte ihren Rahmen aktualisieren. Keine Warnungen und keine Fehler. Weil alle Einschränkungen gegen die Inhaltsansicht gerichtet sind.

UIScrollView berechnet die Größe der Inhaltsansicht gemäß den Einschränkungen der inneren Ansichten. (Für das Beispiel ist die Inhaltsgröße: Breite = 100 (vorderer Bereich) + 200 (Breite der Ansicht) + 500 (nachfolgender Bereich), Höhe = 131 (oberer Abstand) + 200 (Höhe) + 269 (unterer Abstand)

So fügen Sie Einschränkungen für Ansichten in UIScrollView hinzu:

  1. Abbildung der Positionen von Ansichten in der Inhaltsansicht.
  2. Fügen Sie den Rändern der Inhaltsansicht einen Abstand von oben, rechts, unten und links hinzu sowie die Breite und Höhe dieser Ansichten.

Und alles ist erledigt.

Eine einfache Möglichkeit, mit AutoLayout mit Bildlaufansicht umzugehen, besteht darin, eine Containeransicht hinzuzufügen, die alle Unteransichten in der Bildlaufansicht enthält.

Schlussfolgerung: Der wichtigste Punkt zum Verständnis von AutoLayout mit UIScrollView sind innere Ansichten, die Einschränkungen für die Inhaltsansicht, nicht jedoch für UIScrollView selbst festlegen.

angehängter Beispielcode

Danyun Liu
quelle
5

Die folgende Lösung funktionierte für mich für scrollView mit Autolayout und ohne contentSize :

  1. Ziehen Sie eine Bildlaufansicht per Drag & Drop auf viewController und wenden Sie alle Einschränkungen an, um den gewünschten Bereich abzudecken.
  2. Ziehen Sie eine UIView per Drag & Drop in die scrollView und lassen Sie sie den gesamten Bereich der scrollView abdecken. Wenden Sie die Einschränkungen so an, dass sie in scrollView oben, links, rechts und unten liegen.
  3. Stellen Sie die Höhe (und Breite, wenn horizontales Scrollen erforderlich ist) der Innenansicht gemäß den Anforderungen des Scrollens ein. Dieser Teil kann bei Bedarf auch aus Code ausgeführt werden.
  4. Kritisch . Nachdem Sie die Höhe in Punkt (3) auf einen großen Wert eingestellt haben, kehren Sie zu Punkt (2) zurück und stellen Sie sicher, dass die oberen, linken, rechten und unteren Werte wieder auf Null gesetzt werden, da Xcode sie möglicherweise beim Erzwingen für Sie geändert hat änderte die Höhe in (3).

Und du bist fertig. Jetzt können Sie dieser Ansicht eine beliebige Anzahl von Steuerelementen hinzufügen und die für einander relevanten Einschränkungen anwenden (die ohne diese Ansicht nicht funktionieren). Wenn Sie diese Ansicht nicht verwenden möchten, müssen Sie Einschränkungen für jedes Steuerelement anwenden, das sich auf scrollView bezieht (nicht aufeinander bezogen).


Der überwältigende Tipp ..............

Kritisch . Nehmen wir zur Klarheit an, die UIScrollView ist 1000 breit und 100 hoch. (Normalerweise sind diese Werte natürlich dynamisch, abhängig von der Breite des Geräts usw. Aber sagen Sie vorerst nur 1000 breit und 100 hoch.) Nehmen wir an, Sie führen einen horizontalen Bildlauf durch. Fügen Sie also eine UIView in die UIScrollView ein. (Dies ist die "Inhaltsansicht".) Legen Sie alle vier Einschränkungen der Inhaltsansicht oben, unten, nach oben und nach hinten in der Bildlaufansicht fest. Machen Sie sie alle auf Null, auch wenn das falsch erscheint. Stellen Sie die Höhe des Inhalts-UIView auf 100 ein und vergessen Sie das. Jetzt: Sie möchten horizontal scrollen, stellen Sie also die Breite der Inhaltsansicht auf 1225 ein.

Beachten Sie, dass die Breite der Inhaltsansicht jetzt 225 größer ist als die Breite der übergeordneten Bildlaufansicht. Das ist in Ordnung: Tatsächlich MÜSSEN Sie das tun. Beachten Sie, dass

... Sie setzen die nachlaufende Breite NICHT auf negativ 225 ...

Sie würden denken, Sie müssten die Breiten wie gewohnt "anpassen" . Aber wenn Sie das tun, wird es überhaupt nicht funktionieren.

Sie müssen die führenden und nachfolgenden Zahlen auf NULL setzen , niemals negativ (obwohl die Breite "größer" ist).

Interessanterweise können Sie die führenden / nachfolgenden Zahlen auf einen beliebigen positiven Wert setzen (versuchen Sie, "50" zu sagen), und Sie erhalten eine Art Absprungspielraum. (Es sieht oft gut aus: probieren Sie es aus.) Jeder negative Wert an beiden Enden wird "lautlos brechen".

Beachten Sie, dass ärgerlicherweise oft Xcode (ab 7.3.1 sowieso),

wird 'hilfreich' diese Werte für Sie auf negative Zahlen setzen!

weil es versucht, sie automatisch für Sie zu zählen. Wenn ja, wird es lautlos brechen. Setzen Sie zunächst alle vier Werte auf Null. Stellen Sie die Breite der Inhaltsansicht viel breiter als die "1000" im Beispiel ein.


Bearbeitet: Ich habe für den größten Teil meiner Anforderungen UITableView anstelle von UIScrollView verwendet. Als tableView erscheint mir viel flexibler und dynamischer.

Zeeawan
quelle
Dies ist eigentlich die beste Antwort hier. Vielen Dank!
Fattie
4

Ich gehe davon aus, dass Sie auf Probleme mit dem stoßen contentSize. In diesem BlogbeitragcontentSize erfahren Sie, wie Sie mit einem "reinen" AutoLayout-Ansatz umgehen. Der Kern davon ist, dass Ihre Einschränkungen implizit die Inhaltsgröße definieren. Sie legen es NIEMALS explizit fest, wenn Sie AutoLayout verwenden. Ich habe am Ende des Blogposts ein Beispielprojekt angehängt, um zu demonstrieren, wie es funktioniert

Edward Huynh
quelle
3

In den technischen Notizen befindet sich ein Teil, den Sie möglicherweise durchgesehen haben. Sie können die Inhaltsgröße einer Bildlaufansicht implizit mithilfe von Einschränkungen festlegen, die an den Rändern der Bildlaufansicht festgelegt sind.

Hier ist ein einfaches Beispiel. Erstellen Sie ein Storyboard mit einer Ansicht und einer Bildlaufansicht. Stellen Sie die Einschränkungen für Bildlaufansichten so ein, dass sie der Größe der Ansicht entsprechen, in die Sie sie eingefügt haben.

Fügen Sie in dieser Bildlaufansicht eine einzelne Ansicht hinzu. Legen Sie die Größe dieser Ansicht mithilfe von Einschränkungen explizit fest (und stellen Sie sicher, dass die Größe größer als die Bildlaufansicht ist).

Fügen Sie dieser inneren Ansicht nun vier weitere Einschränkungen hinzu, und sperren Sie die vier Kanten der inneren Ansicht mit der übergeordneten Bildlaufansicht. Diese vier Einschränkungen bewirken, dass die Inhaltsgröße erweitert wird, um die innere Ansicht zu berücksichtigen.

Wenn Sie mehrere Ansichten zu einer Bildlaufansicht hinzufügen möchten, z. B. horizontal angeordnet, sperren Sie die linke Seite der ersten Unteransicht links von der Bildlaufansicht, sperren die Unteransichten horizontal und rechts Seite der letzten Unteransicht zur rechten Seite der Bildlaufansicht. Diese Einschränkungen würden dazu führen, dass die Inhaltsgröße der Bildlaufansicht erweitert wird, um alle Unteransichten und ihre Einschränkungen zu berücksichtigen.

Travis
quelle
3

Wenn Ihre Frage lautet: "Wie füge ich eine Reihe von UITextFields in eine vertikal scrollende UIScrollView ein, sodass sie sich bei Fokus aus der Tastatur entfernen", lautet die beste Antwort:

Tu es nicht.

Verwenden Sie stattdessen einen UITableViewController mit statischen Zellen.

Sie erhalten dieses Scroll-out-of-the-Way-Verhalten kostenlos und alle Inhaltseinfügungen funktionieren nur, wenn Ihr View Controller in einem UINavigationController angezeigt wird.

Robert Atkins
quelle
3

Sie sollten Ihr Layout so organisieren , dass es 2
ViewControllerViewenthält ScrollView, ScrollViewenthält ContainerView, ContainerViewenthältLabels
Geben Sie hier die Bildbeschreibung ein

Befolgen Sie dann 3 Schritte, um Ihre ScrollViewDose zu scrollen

  1. Einstellstift ScrollView(oben / rechts / unten / links) aufViewControllerView
    • Einstellstift ContainerView(oben / rechts / unten / links) aufScrollView
    • Set Horizontally in Container( nicht setzen Vertically in Container)
    • Label1Stift ( oben / rechts / links) anContainerView
    • Label1Stift (rechts / links / unten ) an ContainerViewund oben anLabel1

Geben Sie hier die Bildbeschreibung ein

HIER ist das Demo-Projekt

Ich hoffe das hilft

Phan Van Linh
quelle
1

Der reine Autolayout-Ansatz funktioniert hervorragend, aber es ist ziemlich mühsam, sich einzurichten, wenn Sie von einem Nicht-Autolayout migrieren. Ich habe es jetzt ein paar Mal gemacht und ich habe ein paar allgemeine Tipps:

  • Fangen Sie klein an: Auch wenn dies bedeutet, dass Sie Ihre Storyboard-Ansichten neu erstellen, beginnen Sie mit nur wenigen Elementen und erstellen Sie Ihre Ansichten langsam. Testen Sie nach dem Hinzufügen einiger Elemente, ob das Scrollen funktioniert.
  • Deaktivieren Sie translatesAutoresizingMaskIntoConstraints für alles: Dies war für mich immer die Ursache für Einschränkungskonflikte.
  • Stellen Sie Ihre UIScrollView-Einschränkungen richtig ein: Stellen Sie sicher, dass die Bildlaufansicht allseitig mit der übergeordneten Ansicht verbunden ist, da sie sonst überhaupt nicht erweitert wird.
Nick
quelle
1

Nachdem ich mich einige Zeit mit diesem Problem befasst hatte, fand ich endlich eine Lösung. Ich arbeite mit Storyboards mit universellen Klassengrößen (600 x 600). Ich habe eine UIView (contentView) in der Größe der scrollView erstellt und Einschränkungen für Top, Bottom, Leading und Trailing to scrollRiew erstellt. Dann habe ich die Größe der contentView manuell auf 600x600 gekürzt. Das Storyboard versuchte nicht mehr, die Größe zu ändern, und ich konnte arbeiten, aber die Ansicht auf dem realen Gerät oder Simulator sah schrecklich aus. Ich habe 2 Constraint-Steckdosen für diese abgeschnittenen Größen hergestellt.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidthConstraint; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewHeightConstraint;

Dann in viewDidLoad

CGSize viewSize = self.view.frame.size;
self.contentViewWidthConstraint.constant = viewSize.width;
self.contentViewHeightConstraint.constant = viewSize.height;

Funktioniert super.

Cristian Pena
quelle
1

Ich habe tagelang versucht, eine Lösung für die Verwendung der AutoLayout-Ansicht einer eingebetteten Bildlaufansicht zu finden, um die Bildlaufansicht auf dem sichtbaren Bildschirm zu zentrieren, der für alle Geräte / Bildschirmabmessungen sowie für die Bildschirmdrehung funktioniert.

Ich habe Tage damit verbracht, es nur mit Autolayout zu versuchen, und bin nah dran, aber nie nah genug dran. Am Ende musste ich also auch 3 Codezeilen pro Bildschirm in viewDidLoad hinzufügen.

Siehe Lösung unten:

  1. Erstellen Sie die Bildlaufansicht und füllen Sie sie mit den gewünschten Objekten
  2. Aktivieren Sie das automatische Layout
  3. Zentrieren Sie dann die ScrollView vertikal und horizontal ScrollView zentrieren
  4. Wählen Sie die Ansicht und dann 'Fehlende Einschränkungen hinzufügen' - das macht dann seine Sache
  5. Das Ergebnis ist, dass viele Einschränkungen generiert werden. Für die Ansicht wurden zwei neue erstellt: "Horiz Space Scrollview to View" und "Vert Space Scrollview to View" oder umgekehrt.
  6. Löschen Sie die 'Horiz Space Scrollview to View', damit Sie jetzt 3 Einschränkungen für die Ansicht haben. Die 2 zum Eingeben der Bildlaufansicht in die Ansicht und die 2 zum Festlegen eines vertikalen Abstands zwischen der Bildlaufansicht und der Ansicht
  7. Verknüpfen Sie nun die Vert-Einschränkung mit Ihrem Code, indem Sie darauf klicken und bei gedrückter Strg-Taste in die Header-Datei ziehen und ein NSLayoutConstraint-IBOutlet erstellen (ich habe meine Einschränkung vertVtoSV genannt).
  8. Gehen Sie nun zur .m-Datei und fügen Sie diese Codezeilen in viewDidLoad ein (spielen Sie mit dem Füllbetrag, um die richtige Vert-Zentrierung zu erhalten).

    if (IPAD)

    {self.constraintVertVtoSV.constant = 150.0; }}

  9. Dies sollte nun auf allen Geräten ausgeführt werden und richtig zentriert sein und trotzdem richtig scrollen.

Kerl
quelle
1

Wenn Sie wie ich nur statischen Inhalt ohne Einschränkungen in der Unteransicht verwenden, können Sie Folgendes tun:

override func viewDidLayoutSubviews() {
    scrollView.contentSize = CGSizeMake(320, 800)
}
Antzi
quelle
1

Ähnliches Problem habe ich heute mit iOS 8.4, Xcode 6.4

Dort eine Ansicht mit einer Bildlaufansicht, die eine Inhaltsansicht (UIView) mit Unteransichten enthält.

Alles ist überall automatisch angeordnet. Die Kanten der Bildlaufansicht werden mit Einschränkungen an die Kanten der übergeordneten Ansichten angeheftet. Die Kanten der Inhaltsansicht werden mit Einschränkungen an die Kanten der Bildlaufansicht angeheftet.

Ursprünglich weigerte sich die Inhaltsansicht, die Größe als volle Breite der Bildlaufansicht zu bestimmen. Ich musste der Inhaltsansicht eine zusätzliche Einschränkung hinzufügen, damit ihre Breite mit der übergeordneten Bildlaufansicht übereinstimmt. Oder ich könnte eine contentView.centerX == scrollView.centerX-Einschränkung festlegen. Bei einer dieser Optionen wurde zusätzlich zum Fixieren der Kanten plötzlich die richtige Größe für die Inhaltsansicht festgelegt.

// Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))

Anheften der Ränder der Inhaltsansicht an die Bildlaufansicht unter Verwendung visueller Einschränkungen des Formulars.

let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]

Ich benutze eine Routine, um das Array zu durchlaufen und sie der scrollView hinzuzufügen.

David
quelle
1

Ich hatte ein ähnliches Problem. Ich habe alle Einschränkungen festgelegt und mich immer gefragt, warum die Größe einiger Unteransichten immer noch geändert wird. Meine Lösung bestand darin, clipsToBounds auf YES zu setzen.

i89
quelle
1

In Kürze können Sie diese funktionierende Lösung verwenden.

Einschränkungen

ScrollView: Führen, Nachlaufen, Oben, Unten = Übersicht

ContentView: Führend, nachlaufend, oben, unten = ScrollView. Höhe fest / relativ zum Inhalt.

Sie können die Breitenbeschränkung (contentView) so einstellen, dass sie der Ansicht der Bildlaufansichten entspricht. Wählen Sie jedoch Entfernen zum Zeitpunkt der Erstellung entfernen, da Sie diese Einschränkung programmgesteuert hinzufügen. Dies ist nur so, damit sich der IB nicht mit Warnungen beschwert.

extension UIView {

    func setupContentViewForViewWithScroll(contentView vwContent : UIView) {
        //Set constraint for scrollview content
        let constraint = NSLayoutConstraint(item: vwContent, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.size.width)
        vwContent.addConstraint(constraint)
        self.layoutSubviews()
    }

}

Und im View Controller viewDidLayoutSubviewsnenne ich einfach diese Methode:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.view.setupContentViewForViewWithScroll(contentView: vwContent)
}
Ibrahim Yildirim
quelle
0

Ich weiß, dass dies eine Lösung für Laien ist und nicht das, was Apple im Dokument vorschlägt, aber es hat bei mir zweimal funktioniert, mit unterschiedlichen Inhalten und kann sehr schnell eingerichtet werden: Fügen Sie im Storyboard View Controller UIView ein. Fügen Sie in UIView eine Tabellenansicht, Dynamic, 0 Prototype-Zellen, Style Plain oder Grouped ein. Fügen Sie in der Tabellenansicht eine Bildlaufansicht ein, und fügen Sie in der Bildlaufansicht Inhalte ein. Das war's, keine Einstellungen im Custom View Controller.

Rinaldo
quelle