Kann UIStackView scrollen?

210

Angenommen, ich habe in UIStackView weitere Ansichten hinzugefügt, die angezeigt werden können. Wie kann ich den UIStackViewBildlauf durchführen?

itsaboutcode
quelle
Warum verwenden Sie keine Bildlaufansicht mit einer (oder mehreren) Stapelansichten für den Inhalt?
Wain
2
Die Ein-Satz-Lösung besteht darin, dass Sie für die Breite bei gedrückter Ctrl-Taste in die Bildlaufansicht der Großeltern ziehen, NICHT in die übergeordnete Stapelansicht. Erklärt in meiner Antwort!
Fattie
Einbetten von UIStackView in UIScrollView in iOS github.com/onmyway133/blog/issues/324
onmyway133
Zu dieser kritischen Frage in iOS. Tatsächlich gibt es zwei (und nur zwei) Möglichkeiten, dies zu tun - dies ist die einzige Möglichkeit, und Sie müssen genau eines der beiden Verfahren befolgen. Meine Antwort unten wird immer aktualisiert.
Fattie
JA. Sie MÜSSEN eine Zwischen-UIView als Inhaltsansicht von UIScrollView haben. Platzieren Sie dann UIStackView als untergeordnete Ansicht der Inhaltsansicht. raywenderlich.com/…
poGUIst

Antworten:

577

Für den Fall, dass jemand nach einer Lösung ohne Code sucht , habe ich ein Beispiel erstellt, um dies mithilfe des automatischen Layouts vollständig im Storyboard zu tun.

Sie können es von Github bekommen .

Grundsätzlich, um das Beispiel neu zu erstellen (für vertikales Scrollen):

  1. Erstellen Sie ein UIScrollViewund legen Sie die Einschränkungen fest.
  2. Fügen Sie ein UIStackViewzum hinzuUIScrollView
  3. Legen Sie die Einschränkungen: Leading, Trailing, Topund Bottomsollten auf diejenigen gleich ausUIScrollView
  4. Richten Sie eine gleiche WidthEinschränkung zwischen UIStackViewund ein UIScrollView.
  5. Stellen Sie die Achse = Vertikal, Ausrichtung = Füllen, Verteilung = Gleicher Abstand und Abstand = 0 auf der ein UIStackView
  6. In einer Reihe von UIViewsauf dieUIStackView
  7. Lauf

Austausch Widthfür die Heightin Schritt 4 und Satz Axis= Horizontalin Schritt 5 eine horizontale UIStackView zu erhalten.

Arjan
quelle
55
Vielen Dank! "4. Richten Sie eine Einschränkung für die gleiche Breite zwischen UIStackView und UIScrollView ein." war der Schlüssel;)
Blank
19
Nummer 6. ist auch wichtig. Wollte alle Ansichten im Code hinzufügen, aber dann zeigt das automatische Layout fehlende Einschränkungen in IB an.
vor dem
11
Hallo Leute, es scheint, dass diese Lösung beim horizontalen Scrollen nicht funktioniert. In Schritt 4 gehe ich davon aus, dass anstelle der gleichen Breite die gleiche Höhe und Achse = Horizontal eingestellt wird. Ich habe das versucht und funktioniert nicht.
Seto Elkahfi
5
Durch Hinzufügen einer Einschränkung, sodass die Stapelansicht und die Bildlaufansicht gleich breit sind, werden Warnungen aus dem Schnittstellen-Generator entfernt, das Bildlauf wird jedoch deaktiviert. Das Scrollen geschieht nur, wenn die Inhaltsansicht in der Bildlaufansicht größer als die Bildlaufansicht ist!
Jason Moore
6
Um auf Punkt 6 näher einzugehen. Wenn die Stapelansicht keine Elemente enthielt, aber alle Einschränkungen vorhanden sind, erhalten Sie "Bildlaufansicht Einschränkungen für Y-Position oder -Höhe erforderlich". Durch einfaches Hinzufügen eines Etiketts in der Stapelansicht verschwindet diese Warnung!
Faisal Memon
45

Apples Auto Layout Guide enthält einen ganzen Abschnitt über das Arbeiten mit Bildlaufansichten . Einige relevante Ausschnitte:

  1. Befestigen Sie die oberen, unteren, vorderen und hinteren Kanten der Inhaltsansicht an den entsprechenden Kanten der Bildlaufansicht. Die Inhaltsansicht definiert jetzt den Inhaltsbereich der Bildlaufansicht.
  2. (Optional) Um das horizontale Scrollen zu deaktivieren, stellen Sie die Breite der Inhaltsansicht gleich der Breite der Bildlaufansicht ein. Die Inhaltsansicht füllt jetzt die Bildlaufansicht horizontal aus.
  3. (Optional) Um das vertikale Scrollen zu deaktivieren, stellen Sie die Höhe der Inhaltsansicht auf die Höhe der Bildlaufansicht ein. Die Inhaltsansicht füllt jetzt die Bildlaufansicht horizontal aus.

Außerdem:

Ihr Layout muss die Größe der Inhaltsansicht vollständig definieren (außer in den Schritten 5 und 6). … Wenn die Inhaltsansicht größer als die Bildlaufansicht ist, ermöglicht die Bildlaufansicht das vertikale Scrollen. Wenn die Inhaltsansicht breiter als die Bildlaufansicht ist, ermöglicht die Bildlaufansicht das horizontale Scrollen.

Zusammenfassend muss die Inhaltsansicht der Bildlaufansicht (in diesem Fall eine Stapelansicht) an ihren Rändern befestigt werden und ihre Breite und / oder Höhe anderweitig eingeschränkt sein. Dies bedeutet, dass der Inhalt der Stapelansicht (direkt oder indirekt) in der Richtung (den Richtungen) eingeschränkt werden muss, in der das Scrollen gewünscht wird. Dies kann beispielsweise bedeuten, dass jeder Ansicht in einer vertikal scrollenden Stapelansicht eine Höhenbeschränkung hinzugefügt wird. Im Folgenden finden Sie ein Beispiel für das vertikale Scrollen einer Bildlaufansicht mit einer Stapelansicht:

// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
Titandecoy
quelle
1
Vielen Dank, aber das Weglassen der Höhenbeschränkung (um vertikales Scrollen zu ermöglichen) führt zu diesem Fehler im Storyboard: Need constraints for: Y position or height.Dieser Fehler wird nur behoben, wenn Sie sowohl eine Breiten- als auch eine Höhenbeschränkung für die Stapelansicht festlegen, wodurch das vertikale Scrollen deaktiviert wird. Funktioniert dieser Code noch für Sie?
Crashalot
@Crashalot Um diesen Fehler zu beseitigen, müssen Sie der Stapelansicht eine Unteransicht hinzufügen. siehe meine Antwort unten.
pkamb
16

Die Einschränkungen in der Antwort mit der höchsten Abstimmung hier haben für mich funktioniert, und ich habe ein Bild der Einschränkungen unten eingefügt, die in meinem Storyboard erstellt wurden.

Ich habe jedoch zwei Probleme festgestellt, die anderen bewusst sein sollten:

  1. Nach dem Hinzufügen von Einschränkungen, die denen in der akzeptierten Antwort ähneln, wird der rote Autolayout-Fehler angezeigt Need constraints for: X position or width. Dies wurde gelöst, indem ein UILabel als Unteransicht der Stapelansicht hinzugefügt wurde.

    Ich füge die Unteransichten programmgesteuert hinzu, sodass ich ursprünglich keine Unteransichten im Storyboard hatte. Um die Autolayout-Fehler zu beseitigen, fügen Sie dem Storyboard eine Unteransicht hinzu und entfernen Sie sie beim Laden, bevor Sie Ihre tatsächlichen Unteransichten und Einschränkungen hinzufügen.

  2. Ich habe ursprünglich versucht, UIButtonsUIStackView hinzuzufügen. Die Schaltflächen und Ansichten würden geladen, die Bildlaufansicht jedoch nicht . Dies wurde durch Hinzufügen gelöstUILabels anstelle von Schaltflächen zur Stapelansicht . Unter Verwendung der gleichen Einschränkungen wird in dieser Ansichtshierarchie mit den UILabels gescrollt, in den UIButtons jedoch nicht.

    Ich bin von diesem Problem verwirrt, da die UIButtons Sie scheinen eine IntrinsicContentSize zu haben (wird von der Stapel - Ansicht). Wenn jemand weiß, warum die Tasten nicht funktionieren, würde ich gerne wissen, warum.

Hier ist meine Ansichtshierarchie und Einschränkungen als Referenz:

Einschränkungen für die Stapelansicht in der Bildlaufansicht [1]

pkamb
quelle
3
Sie haben mir nur ein paar Stunden Kopfstoß gegen die Wand und Frustration erspart. Ich bin in genau der gleichen Situation und konnte den Grund der Warnung nicht herausfinden und warum ich nicht mit Knöpfen arbeite. Warum Apple warum?
PakitoV
15

Wie Eik sagt UIStackViewund gut UIScrollViewzusammen spielt, siehe hier .

Der Schlüssel ist, dass der UIStackViewdie variable Höhe / Breite für verschiedene Inhalte handhabt und UIScrollViewdann seine Aufgabe gut erledigt, diesen Inhalt zu scrollen / zu springen:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)       
}
user1307434
quelle
2
Es ist nicht erforderlich, manuelles und automatisches Layout zu kombinieren, um eine scrollbare Stapelansicht zu ermöglichen. Sie müssen lediglich die Breite und / oder Höhe der Stapelansicht einschränken. Weitere Informationen und einen Link zu den entsprechenden Apple-Dokumenten finden Sie in meiner Antwort.
titaniumdecoy
Das Github-Beispiel funktionierte perfekt und war sehr klar. Danke für das Teilen.
Behr
stackView.translatesAutoresizingMaskIntoConstraints = false, dies hat in meinem Fall den Trick getan
Howl Jenkins
10

Ich wollte das Gleiche tun und bin auf diesen ausgezeichneten Beitrag gestoßen . Wenn Sie dies programmgesteuert mithilfe der Anker-API tun möchten, ist dies der richtige Weg.

Um es zusammenzufassen, binden Sie Ihre UIStackViewin Ihre ein UIScrollViewund legen Sie die Ankereinschränkungen von so fest UIStackView, dass sie mit denen der folgenden übereinstimmen UIScrollView:

stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
Dalmazio
quelle
Bitte fügen Sie nicht dieselbe Antwort auf mehrere Fragen hinzu. Beantworten Sie die beste Frage und markieren Sie den Rest als Duplikate. Siehe Ist es akzeptabel, mehrere Fragen doppelt zu beantworten?
FelixSFD
10
In diesem Fall handelt es sich nicht wirklich um Duplikate. Die andere Frage fragt speziell, wie es programmgesteuert gemacht werden soll, während dies nicht der Fall ist. In der Tat bietet die beste Antwort auf diese Frage eine GUI-Methode, um das Ergebnis zu erzielen. Dennoch kann eine programmatische Lösung für einige Benutzer wertvoll sein.
Dalmazio
9

Aktuell für 2020.

100% Storyboard ODER 100% Code.


Hier ist die einfachste mögliche Erklärung:

  1. Haben Sie eine leere Vollbildszene

  2. Fügen Sie eine Bildlaufansicht hinzu. Ziehen Sie bei gedrückter Ctrl-Taste von der Bildlaufansicht in die Basisansicht , fügen Sie links-rechts-oben-unten und alle Null hinzu.

  3. Fügen Sie der Bildlaufansicht eine Stapelansicht hinzu. Ziehen Sie bei gedrückter Ctrl-Taste von der Stapelansicht in die Bildlaufansicht , fügen Sie links-rechts-oben-unten und alle Null hinzu.

  4. Legen Sie zwei oder drei Etiketten in die Stapelansicht.

Machen Sie aus Gründen der Klarheit die Hintergrundfarbe des Etiketts rot. Stellen Sie die Etikettenhöhe auf 100 ein.

  1. Stellen Sie nun die Stellen Sie Breite jedes UILabels ein:

    Überraschenderweise Steuertaste von der UILabelauf die Bildlaufansicht, nicht auf den Stapel Ansicht und wählen gleiche Breiten .

Wiederholen:

Kontrollieren Sie nicht das Ziehen vom UILabel zum Elternteil des UILabels - gehen Sie zum Großelternteil. (Mit anderen Worten, gehen Sie bis zur Bildlaufansicht und nicht bis zur Stapelansicht.)

So einfach ist das. Das ist das Geheimnis.

Geheimtipp - Apple Bug:

Es wird nicht mit nur einem Artikel funktionieren ! Fügen Sie einige Beschriftungen hinzu, damit die Demo funktioniert.

Du bist fertig.

Tipp: Sie müssen jedem neuen Element eine Höhe hinzufügen . Jedes Element in einer Bildlaufstapelansicht muss entweder eine Eigengröße (z. B. eine Beschriftung) haben oder eine explizite Höhenbeschränkung hinzufügen.


Der alternative Ansatz:

Oben: Stellen Sie überraschenderweise die Breite der UILabels auf die Breite der Bildlaufansicht (nicht der Stapelansicht) ein.

Abwechselnd...

Ziehen Sie von der Stapelansicht in die Bildlaufansicht und fügen Sie eine Einschränkung "Breite gleich" hinzu. Das scheint seltsam, weil Sie bereits links-rechts gepinnt haben , aber so machen Sie es . Egal wie seltsam es scheint, das ist das Geheimnis.

Sie haben also zwei Möglichkeiten:

  1. Überraschenderweise stellen Sie die Breite jedes Elements in der Stapelansicht auf die Breite des Großelternteils der Bildlaufansicht ( nicht des übergeordneten Stapels ) ein.

oder

  1. Überraschenderweise setzen Sie eine "Breite gleich" der Stapelansicht auf die Bildlaufansicht - obwohl Sie den linken und rechten Rand der Stapelansicht ohnehin an die Bildlaufansicht angeheftet haben.

Um klar zu sein, machen Sie EINE dieser Methoden, machen Sie NICHT beide.

Fattie
quelle
8

Horizontales Scrollen (UIStackView in UIScrollView)

Zum horizontalen Scrollen. Erstellen Sie zunächst ein UIStackViewund ein UIScrollViewund fügen Sie sie folgendermaßen zu Ihrer Ansicht hinzu:

let scrollView = UIScrollView()
let stackView = UIStackView()

scrollView.addSubview(stackView)
view.addSubview(scrollView)

In Erinnerung an die zu setzen , translatesAutoresizingMaskIntoConstraintsum falseauf dem UIStackViewund die UIScrollView:

stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false

Damit alles funktioniert, sollten die nachlaufenden, führenden, oberen und unteren Anker UIStackViewder UIScrollViewAnker gleich sein:

stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

Aber der Breitenanker des UIStackViewMosts muss gleich oder größer als die Breite des UIScrollViewAnkers sein:

stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true

Verankern Sie jetzt UIScrollViewzum Beispiel:

scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true 

Als nächstes würde ich vorschlagen, die folgenden Einstellungen für die UIStackViewAusrichtung und Verteilung zu versuchen :

topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center

topicStackView.spacing = 10

Schließlich müssen Sie die addArrangedSubview:Methode verwenden, um Ihrem UIStackView Unteransichten hinzuzufügen.

Texteinfügungen

Ein zusätzliches Merkmal , dass Sie nützlich finden könnten , ist , dass , weil die UIStackViewinnerhalb einer gehalten wird UIScrollViewnun Sie den Zugriff auf Texteinschübe haben , um die Dinge sehen ein bisschen schöner.

let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset

// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true
skizzenhaftTech
quelle
7

Fügen Sie dies einfach hinzu zu viewdidload:

let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets

Quelle: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

Rashad.Z
quelle
Ich kann Ihnen nicht sagen, wie sehr dies meine Probleme mit Autolayout + ScrollView gerettet hat. Toller Fund auf diesem Apple-Link.
ded
was macht das Was passiert ohne das?
Honig
Dadurch wird nur der Inhalt der Bildlaufansicht unterhalb der Statusleiste platziert.
Turing getestet
2

Sie können ScrollableStackView ausprobieren : https://github.com/gurhub/ScrollableStackView

Es ist eine Objective-C- und Swift-kompatible Bibliothek. Es ist über CocoaPods erhältlich .

Beispielcode (Swift)

import ScrollableStackView

var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)

// add your views with 
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...

Beispielcode (Ziel-C)

@import ScrollableStackView

ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];

UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];

// add your views with
[scrollable.stackView addArrangedSubview:rectangle]; 
// ...
mgyky
quelle
Hallo Peter, eigentlich eine tolle Idee! Beiträge sind immer willkommen, bitte senden Sie uns eine Pull-Anfrage. Beste.
mgyky
0

Wenn Sie die Stapelansicht vertikal in der Bildlaufansicht zentrieren müssen, entfernen Sie sie einfach.

Ahmed Elashker
quelle
0

Beispiel für eine vertikale Stapelansicht / Bildlaufansicht (mit der Option für das automatische Layout EasyPeasy):

let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
    Edges(),
    Width().like(self.view)
]

let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill    
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
    Edges(),
    Width().like(self.view)
]

Stellen Sie einfach sicher, dass jede Höhe Ihrer Unteransicht definiert ist!

dOM
quelle
0
  1. Entwerfen Sie in erster Linie Ihre Ansicht, vorzugsweise in einer Art Skizze, oder machen Sie sich ein Bild davon, was Sie als scrollbaren Inhalt wünschen.

  2. Machen Sie danach die freie Form des Ansichtscontrollers (wählen Sie aus dem Attributinspektor) und stellen Sie Höhe und Breite gemäß der inhaltlichen Größe Ihrer Ansicht ein (aus dem Größeninspektor auszuwählen).

  3. Danach legen Sie im Ansichts-Controller eine Bildlaufansicht ab. Dies ist eine Logik, die in iOS fast immer funktioniert (möglicherweise muss die Dokumentation dieser Ansichtsklasse durchgesehen werden, die Sie über Befehl + Klicken erhalten können diese Klasse oder über googeln)

    Wenn Sie mit zwei oder mehr Ansichten arbeiten, beginnen Sie zuerst mit einer Ansicht, die früher eingeführt wurde oder primitiver ist, und wechseln Sie dann zu der Ansicht, die später eingeführt wurde oder moderner ist. Beginnen Sie hier also, da zuerst die Bildlaufansicht eingeführt wurde, zuerst mit der Bildlaufansicht und wechseln Sie dann zur Stapelansicht. Setzen Sie hier die Einschränkungen für die Bildlaufansicht in alle Richtungen gegenüber der Superansicht auf Null. Fügen Sie alle Ihre Ansichten in diese Bildlaufansicht ein und fügen Sie sie dann in die Stapelansicht ein.

Während der Arbeit mit der Stapelansicht

  • Beginnen Sie zuerst mit Grounds Up (Bottom-Up-Ansatz), dh wenn Sie Beschriftungen, Textfelder und Bilder in Ihrer Ansicht haben, legen Sie diese Ansichten zuerst an (in der Bildlaufansicht) und fügen Sie sie anschließend in die Stapelansicht ein.

  • Danach optimieren Sie die Eigenschaft der Stapelansicht. Wenn die gewünschte Ansicht immer noch nicht erreicht wird, verwenden Sie eine andere Stapelansicht.

  • Wenn dies immer noch nicht erreicht wird, spielen Sie mit Kompressionsbeständigkeit oder inhaltlicher Priorität.
  • Fügen Sie anschließend der Stapelansicht Einschränkungen hinzu.
  • Denken Sie auch daran, eine leere UIView als Füllansicht zu verwenden, wenn alle oben genannten Ergebnisse nicht zufriedenstellend sind.

Fügen Sie nach dem Erstellen Ihrer Ansicht eine Einschränkung zwischen der Mutterstapelansicht und der Bildlaufansicht ein, während die untergeordnete Stapelansicht mit der Mutterstapelansicht eingeschränkt wird. Hoffentlich sollte es zu diesem Zeitpunkt gut funktionieren, oder Sie erhalten eine Warnung von Xcode mit Vorschlägen, lesen Sie die darin enthaltenen Informationen und implementieren Sie diese. Hoffentlich sollten Sie jetzt eine Arbeitssicht haben, die Ihren Erwartungen entspricht :).

Nikhil Pandey
quelle
0

Für die verschachtelte oder einzelne Stapelansicht muss die Bildlaufansicht mit der Stammansicht auf eine feste Breite eingestellt werden. Die Hauptstapelansicht innerhalb der Bildlaufansicht muss dieselbe Breite haben. [Meine Bildlaufansicht befindet sich unten in einer Ansicht. Ignorieren Sie sie.]

Richten Sie eine Einschränkung für die gleiche Breite zwischen UIStackView und UIScrollView ein.

Geben Sie hier die Bildbeschreibung ein

Md Imran Choudhury
quelle
0

Wenn jemand nach einer horizontalen Bildlaufansicht sucht

func createHorizontalStackViewsWithScroll() {

 self.view.addSubview(stackScrollView)
 stackScrollView.translatesAutoresizingMaskIntoConstraints = false
 stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
 stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
 stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
 stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
 stackScrollView.addSubview(stackView)

 stackView.translatesAutoresizingMaskIntoConstraints = false
 stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
 stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
 stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
 stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
 stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true

 stackView.distribution = .equalSpacing
 stackView.spacing = 5
 stackView.axis = .horizontal
 stackView.alignment = .fill


 for i in 0 ..< images.count {
 let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
 // set button image
 photoView.translatesAutoresizingMaskIntoConstraints = false
 photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
 photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true

 stackView.addArrangedSubview(photoView)
 }
 stackView.setNeedsLayout()

 }
user1039695
quelle
0

Platzieren Sie eine Bildlaufansicht in Ihrer Szene und passen Sie sie so an, dass sie die Szene ausfüllt. Platzieren Sie dann eine Stapelansicht in der Bildlaufansicht und die Schaltfläche Element hinzufügen in der Stapelansicht. Sobald alles vorhanden ist, legen Sie die folgenden Einschränkungen fest:

Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width

Geben Sie hier die Bildbeschreibung ein

Code: Stack View.Width = Scroll View.Widthist der Schlüssel.

Joshua Cleetus
quelle
0

Hinzufügen einer neuen Perspektive für macOS Catalyst. Da MacOS-Apps die Größenänderung von Fenstern unterstützen, ist es möglich, dass Sie UIStackViewvon einem nicht scrollbaren Status zu einem scrollbaren Status wechseln oder umgekehrt. Hier gibt es zwei subtile Dinge:

  • UIStackView ist für alle Bereiche geeignet.
  • Während des Übergangs UIScrollViewwird versucht, die Größe zu ändern, um den neu gewonnenen / verlorenen Bereich unter Ihrer Navigationsleiste (oder die Symbolleiste bei macOS-Apps) zu berücksichtigen.

Dies wird leider eine Endlosschleife erzeugen. Ich bin nicht sehr vertraut mit UIScrollViewund seine adjustedContentInset, aber aus meinem Protokoll in seiner layoutSubviewsMethode sehe ich das folgende Verhalten:

  • Man vergrößert das Fenster.
  • UIScrollView versucht, seine Grenzen zu verkleinern (da der Bereich unter der Symbolleiste nicht benötigt wird).
  • UIStackView folgt.
  • Irgendwie UIScrollViewist er unzufrieden und beschließt, die größeren Grenzen wiederherzustellen. Das fühlt sich für mich sehr seltsam an, da ich das aus dem Protokoll sehe UIScrollView.bounds.height == UIStackView.bounds.height.
  • UIStackView folgt.
  • Fahren Sie dann mit Schritt 2 fort.

Es scheint mir, dass zwei Schritte das Problem beheben würden:

  • Ausrichten UIStackView.topaufUIScrollView.topMargin .
  • Set contentInsetAdjustmentBehaviorzu .never.

Hier geht es um eine vertikal scrollbare Ansicht mit einer vertikal wachsenden UIStackView . Ändern Sie für ein horizontales Paar den Code entsprechend.

Hoffe, es hilft jedem in der Zukunft. Ich konnte niemanden finden, der dies im Internet erwähnte, und es hat mich ziemlich lange gekostet, herauszufinden, was passiert ist.

Minsheng Liu
quelle